<!-- ======================================================================== ObjectMethodMessages DTD: Author: John Tigue <jtigue@datachannel.com> Last edited: 1998.3.#@(_*@#_(*_$(#@*(*$ This version: http://www.datachannel.com/XML/DTD/LCDInterfaceDef-19980403.dtd Latest version: http://www.datachannel.com/XML/DTD/LCDInterfaceDef.dtd Copyright (c) 1998 DataChannel Inc. http://www.datachannel.com These declarations can be referred to as an external entity using either a public ID as as in the following snippet: PUBLIC "-//DataChannel//DTD ObjectMethodMessages V1.0//EN" "http://xml.datachannel.com/ObjectMethodMessages.dtd" or using a system ID such as: SYSTEM "http://xml.datachannel.com/ObjectMethodMessages.dtd" --> <!-- ======================================================================== History: Release 1998.3.19 (John Tigue) First relatively clean pass. Release 1998.3.21 (JFT) More clean up. Factored "complex"s out to the interfaceDef's (making these document types analogous to DCE RPC PDUs; useful for integrating with legacy systems). Release 1998.3.24 (JFT) major redesign of objectReference. some tweeking of ParamEntityDefs. fix misspelling of causalityID. Release 1998.3.24.2 (JFT) "objectMethodCall" and "objectMethodReturn" were renamed to "objectMethodRequest" and "objectMethodResponse" to make the analogy with DCE RPC more explicit. There the basic unit of communication is a PDU (or Protocol Data Unit) with two major types: Request PDU and Response PDU. English clean up. Release 1998.3.25 (JFT) moved "unique" and "constant" elements up to the interfaceDef. sundry tweeks. English clean up. Release 1998.3.26 (JFT) English clean up. Release 1998.3.31 (JFT) 1998.3.30: ObjectReference renamed to ObjectRef, same for the ObjectRefArray. Parameter entiy loquaciousPrimativesOrObjectRefs defined for convenience. Comment clean up. 1998.3.31: satisfied XML processor. Comment clean up. Release NEXT (JFT) 1998.4.5 synched with external parameter entity names --> <!-- ======================================================================== Introductory Note: The goal of these declarations is to express in XML documents the serialized method calls and returns between software component objects. The higher level issue of interface definitions is outside the scope of these declarations. See the InterfaceDef DTD for such issues. This version is not final; it will need to be modified in order to reflect some details of COM+. See: http://www.datachannel.com/developers/WebBroker/ for the latest information. These XML definitions are designed for use as the DTD to defines two types of XML documents: one for serialized object method calls and the other for serialized object method returns which are collectively termed "object method messages". Documents complying to this DTD are expected to declare the document element type as either "objectMethodRequest" or "objectMethodResponse". For example: <!DOCTYPE objectMethodRequest PUBLIC "-//DataChannel//DTD ObjectMethodMessages V1.0//EN" "http://xml.datachannel.com/ObjectMethodMessages.dtd" > Another example: <!DOCTYPE objectMethodResponse SYSTEM "http://xml.datachannel.com/ObjectMethodMessages.dtd" > Note for network and parse efficiency, all the following element and attribute names can be mapped to single chararacter tokens. This is not done here for the sake of human readability. The terse analog of this DTD is available at: http://xml.datachannel.com/system/dtd/TerseObjectMethodMessages.dtd Note: there is no facility for "structs" or "complex" or "composite" structures. Complex data types (corresponding to, for example, C struct) are not addressed in this level of the "stack". These declarations address only how to serialized data into an XML document. The construction of complex data types from a sequence of primatives is the responsability of the marshalling code. Such issues are addressed in the InterfaceDef DTD. This DTD deals only with serialization of data. It is assumed that the proxies and stubs on both ends of the connection know how to marshal and unmarshal the primative data types into possibly higher level constructs. This is analogous to DCE RPC where Request and Response PDUs do not have named data structues. Note that int the ObjectRef element there is no explicit support for "reference counting". Reference counting does not scale well on the Web and it complicates the client and protocol. The Microsoft Transaction Server (MTS) employs a more scalable model where in "state" is seperated from implementation which allows an object to have control over its own "liveness" without that being controlled by reference counts in other processes. Not only is the lack of reference counting more scalable but it keeps the clients and protocol simple. Note that for legacy code these definition are extened by the FullLegacyObjectMethodMessages DTD (which includes these definitions) to include reference counting and other baubles. See: OrnimentedObjectMethodMessages.dtd Try not to use such things as it raised the bar in terms of just how stupid the client can be. Of course this puts more burden on the server programmer but there seems to be no way around that without sacrificing scalability and client simpicity. A later version of this DTD may have the ability to name the data being marshalled. This is useful for situations where parameters are optional and so need to be named to be correctly identified. For this version, correctly sequencing data into a doucument is the responsibility of the proxy and stub. Correctly behaving proxies and stubs can be algorithmically generated from the interfaceDef documents. Named parameters would be accomplished via a mechanism which can enforce uniqueness since the names of the parameters need to be distinct. Thanks to Eve Maler and W. Eliot Kimber for their help. References: IIOP: ???? DCOM: ???? --> <!-- ======================================================================== Here the data typing structures are pulled in. All the structuring from the AnonymousData DTD is used here as it would be in a plain AnonymousData document except for the root element. Whereas an AnonymousData document would have a "data" element as the root of the document, documents which conform to these declarations would have an "objectMethodRequest" or an "objectMethodResponse" element as the root. "data" elements do not occur anywhere in these document instances. Instead, what would be the children of "data" appear as the children of "methodCall" and "methodReturn" elements. Also note that AnonymousData does not have the types "void" or "objectReference" or "objectReferenceArray" which are defined in this document. For more info see: http://xml.datachannel.com/system/dtd/AnonymousData.dtd The parameter entity "loquaciousDataTypes" is also defined in that entity. It is used as shorthand for "any datatype". Here is how it appears in its source: <!ENTITY % loquaciousPrimativeDataTypes "boolean | booleanArray | char | charArray | double | doubleArray | int | intArray | long | longArray | float | floatArray | short | shortArray | byte | byteArray | string | stringArray" > The terse analog of these declarations pulls in the TerseAnonymousData declarations not, as here, the loquacious ones. --> <!ENTITY % loquaciousDataTyping SYSTEM "AnonymousData.dtd" > %loquaciousDataTyping; <!-- the next entity def is simply a convenience --> <!ENTITY % loquaciousPrimativesPlusObjectRefs "%loquaciousPrimativeDataTypes; | objectRef | objectRefArray " > <!-- "void" is needed as the marker that a method with return data type of "void" actually returned successfully. The other possibility is that an exception occured. "void" is the place holder indicating "no exception occured" --> <!ELEMENT void EMPTY> <!-- ======================================================================== "objectMethodRequest" is one of the two intended document root elements defined by these definitions. A calling software component sends one of these documents to another component and an "objectMethodResponse" document is returned to the caller. This is analogous to a DCE RPC Request PDU. --> <!ELEMENT objectMethodRequest (baroque?, methodCall) > <!-- This is equivalent to the COMVERSION in the ORPCTHIS struct for DCOM. Current DCOM has this as 5.3 --> <!ATTLIST objectMethodRequest version CDATA #FIXED "0.9" > <!-- ======================================================================== "baroque" is where the gritty stuff goes. ("baroque" b/ this is elaborate ornimentation). "logicalThread" goes in baroque. "protocolExtensions" goes in baroque. Other unforseen header-like issues would go in there too. This can be though of as analogous to the <head> in <html>. <methodCall> and <methodReturn> correspond to <body> in <html>. Hopefully this contains all the necessary info from DCOM's ORPCTHIS struct. Quoting from the DCOM spec: // implicit 'this' pointer which is the first [in] parameter on // every ORPC call. typedef struct tagORPCTHIS { COMVERSION version; // COM version number unsigned long flags; // ORPCF flags for presence of // other data unsigned long reserved1; // set to zero CID cid; // causality id of caller ORPC_EXTENT_ARRAY* extensions; // [unique] extensions } ORPCTHIS; And likewise for ORPCTHAT except it only has the extensions. Other models would also put their headers in here. "logicalThread" is useful in the response in order to determine which "physical" thread to wake up. It also allows the broker to use one thread to service nested callback (OS efficiency issue) instead of using a new thread each time the callback nests again. Without this id there is the possibility of many physical thread sleeping on the callback stack which are gaurenteed to not have to wake up until the callback unwinds. --> <!ELEMENT baroque ANY> <!-- "logicalThread" is isomorphic to CausalityID from DCOM. It is part of the DCOM Object RPC protocol headers. "logicalThread" should occur only within a "baroque" element's content. --> <!ELEMENT logicalThread EMPTY > <!-- The datatype of the attribute "causalityID" is XML-Data:uuid. ToDo: make data type explicit for the XML-Data processor --> <!ATTLIST logicalThread causalityID CDATA #REQUIRED > <!-- "protocolExtensions" is a general purpose extension mechanism for unforeseen matters. Should occur only within a "baroque" element's content. --> <!ELEMENT protocolExtensions ANY > <!-- ======================================================================== "methodCall" contains the payload of serialized parameters which are being marshalled "in" to the destination component over the Web. One of the two attributes must have an explicit assignment: either the methodID has the element ID of the methodDef from the appropriate LCDInterfaceDef document which describes the interface which defines the method being called or the methodName attribute value is the name of the method being called (weak for polymorphics, requires more smarts on the part of the message reader). (TODO: consider datatyping the attribs when that happens but that might not happen for XPointers) --> <!ELEMENT methodCall ( ( %loquaciousPrimativesPlusObjectRefs; )* ) > <!ATTLIST methodCall methodID CDATA #IMPLIED methodName CDATA #IMPLIED > <!-- ======================================================================== "objectMethodResponse" is one of the two intended document root elements defined by these declarations. A calling software component sends an "objectMethodRequest" document to another software component over the Web and a document with the root element type of "objectMethodResponse" is returned to the caller. The payload may be "out" marshalled parameters (including objectReference(s)), void, or an exception. In the XML processor model, the proxies and stubs are the applications which are using the XML processor. They are expected to know which particular sequence of datatypes should occur per method request and response. The "logicalThread" in the "baroque" element can be used to decide which thread to route the "objecteMethodReturn" to within the destination machine. (TODO: later these declarations will use XML-Data to more strongly structure the marshalling. That will be very useful in situations where parameters can be named an optionally not included in the serialized call). --> <!ELEMENT objectMethodResponse ( baroque?, ( methodReturn | exception ) ) > <!ATTLIST objectMethodResponse version CDATA #FIXED "0.9"> <!ELEMENT methodReturn ( void | ( %loquaciousPrimativesPlusObjectRefs; )* ) > <!-- ======================================================================== exceptions are declarative messages indicating (usually) that something wrong happened. The contents of the "exception" may be different for each document instance. The possibilities are constrained by the interfaceDef doc for the interface being called into. --> <!ELEMENT exception ANY> <!-- For DCOM and not COM+, exception should contain a "DCOMException" which contains the HRESULT el al. for things like the SetErrorInfo and GetErrorInfo Win32 APIs. WebBroker is following the pattern laid down by Microsoft's Java work (see MS's Java SDK, in particular package com.ms.com) and the documentation from COM+. None-the-less it would be best if Microsoft were to define the details of the area. The contents of "DCOMException" is the error info. HRESULTs should be expressed in "DCOMException"s. The objective here, like com.ms.com, is to wrap DCOM HRESULTs in an object oriented fashion. This is what Microsoft wants e.g. their work with IONA. COM+ has exceptions so WebBroker uses exceptions. HRESULTs and their mapping are a "legacy" issue. (TODO: Will want to datatype the HRESULT) (TODO: get more specific ala Microsoft) --> <!ELEMENT DCOMException (#PCDATA) > <!ATTLIST DCOMException HRESULT CDATA #REQUIRED> <!-- ======================================================================== an objectRef is a reference to a software component object somewhere on the Web. It is simply the association of an id URI (usually an address URL) and a type definition i.e. "where is it and what can I do with it". Attributes: xml:link: as per the XML-LINK spec this indicates that this is a link inline: another XML-LINK attribute href: as per the XML-LINK spec, the address of the component object, a URI interfaceDef: the URI for the InterfaceDef which defines the interface The interfaceDef attribute is declared to be of type 'ENTITY' which implies that document instances will have something like the follow in the DTD internal subset: <!NOTATION interfaceDef PUBLIC "-//DataChannel//DTD InterfaceDef//EN" > <!ENTITY someIface SYSTEM "urn:uuid:1" NDATA interfaceDef > (Note: could have gone with entity attribute to refer to external binary entity where entity's notation is interfaceDef or could have gone with NDATA) (TODO: or should that be "interfaceDef NOTATION aSpecificIntefaceUUID" as opposed to "some instance doc of type interfaceDef" in the interfaceDef. Then all we are saying here is its type and in the interfaceDef the interface type checking is done at compile time? I.e. saying that somewhere previously in the doc that the interface was declared but in this DTD we do not know ahead of time what that PUBLIC id will be. This would take some burden off of the OMReq & Resps. Want the one which allows TYPELIB or interfaceDef. Also, dataType the href (ENTITY? don't think so) ) (Note: if you need to map interfaceRefes to this then something like: http://x.y.z/a/b?interface7 is better than http://x.y.z/a/b#interface7 The query term is defined as part of the URI but the fragment is not) (Note: objectRef should map to DCOM OBJREF but that will probably be changing for COM+ so currently holding off on some details. For example, with MTs we no longer need to do reference counting in the objectRef? Don't think we need DCOMs DUALSTRINGARRAY since WebBroker is predicated on HTTP and security is part of the HTTP headers.) --> <!ELEMENT objectRef EMPTY> <!ATTLIST objectRef xml:link CDATA #FIXED "simple" inline CDATA #FIXED "true" href CDATA #REQUIRED interfaceDef ENTITY #REQUIRED > <!-- an array of objectRefs --> <!ELEMENT objectRefArray (objectRef*)>