|
SDLIP DASL Transport Mapping |
SDLIP document map and recommended reading sequence (click to navigate):
This document describes the mapping of the Simple Digital Library Interoperability Protocol (SDLIP-Core) to the
DAV Searching & Locating (DASL) protocol [DASL]. This specification defines how SDLIP
methods are mapped onto DASL messages and discusses compatibility of services using the SDLIP/DASL protocol mapping
and native DASL services. Client or server application builders do not need to understand this mapping. Available
code libraries make the mapping process transparent. However, if you do choose to read this document: knowledge
of DASL is assumed.
The goal of the SDLIP/DASL mapping is (i) to have a comprehensive HTTP transport for SDLIP-client/SDLIP-server interactions, and (ii) to allow as much interaction as possible among SDLIP services and client applications on the one hand, and native DASL services and client applications on the other.
Content:
1. Overview of DASL 2. Search Interface Mapping 2.1 Search Request 2.2 Search Result 2.3 Search Redirection 3. Result Access Interface Mapping 4. Metadata Interface Mapping 5. Exceptions References
The search model of DASL is a stateless request-reply model. The DASL protocol is an application of the HTTP 1.1 protocol. A client search request has the following structure:
SEARCH [server path] HTTP/1.1
Content-type: text/xml
Content-length: ...
[more header values]*
[empty line]
<?xml version="1.0"?>
<d:searchrequest xmlns:d="DAV:">
[search query]
</d:searchrequest>
The type of the search query is uniquely identified by a qualified tag name of the query. A qualified tag is a tag that has a namespace prefix. Every DASL-compliant server has to support a DASL-defined search query format recognized by the tag name DAV:basicsearch. The query schema for the basic search query is specified in [DASL]. The namespace of all DASL XML elements is "DAV:". Note that "DAV:" is a URI schema identifier like "http:", "ftp:" etc.
A successful reply to a search request has the following format:
HTTP/1.1 207 Multi-Status
Content-type: text/xml
Content-length: xxxxx
[more header values]*
[empty line]
<?xml version="1.0"?>
<d:multistatus xmlns:d="DAV:">
[<d:response>...</d:response>]*
</d:multistatus>
DASL supports a single method search whereas SDLIP offers a greater variety of methods. For cases where SDLIP clients communicate with native DASL servers, the only SDLIP method that needs to be mapped onto DASL is therefore the search method in the Search Interface. The ResultAccess Interface methods do not have equivalent counterparts in DASL because all native DASL servers are stateless. When using DASL as transport between SDLIP clients and stateful SDLIP servers, DASL therefore needs additional capabilities. This mapping attempts to add these extensions to DASL as unobtrusively as possible, always attempting to stay within DASL's design framework.
The SDLIP Search Interface defines a single method search whose interface is repeated below for reference:
void search( Long clientSID, // {0} Client-side session ID (unique within client) XMLObject subcols, // {service's default (or sole) subcollection} // Choice of collections to search w/in LSP. XMLObject query, // The query. // (e.g. <ADL:GazeteerLang>Lake Tahoe</ADL:GazeteerLang>) Long numDocs, // {-1} Number of documents to return right away (-1: all) XMLObject docProps, // {all possible properties} Properties to return // for each result doc // (e.g. <propList><Abstract/><Title/>, ...) Long stateTimeoutReq, // {0} Request for number of seconds to // maintain state at server. -1: request unlimited time XMLObject queryOptions, // {none} Additional info for the LSP. OUT Long expectedTotal // {0} -1 if unknowable. -2 if not yet known. OUT Long stateTimeout, // {0} Time server is willing to maintain state OUT Long serverSID, // {0} ID by which server identifies this session OUT XMLObject serverDelegate, // {same as for original query} For followup requests OUT XMLObject result // XML-Encoded result list. )
The next sections describe how the SDLIP search invocation is mapped onto DAV:searchrequest, how the SDLIP search output parameters are extracted from a DAV:multistatus reply, and how redirection is handled.
In all examples below we assume that the namespace shortcut "d" refers to the "DAV:" namespace and the namespace shortcut "s" refers to the SDLIP namespace. One may think of every XML structure below as if every top element of it would have the following two attributes:
xmlns:d="DAV:" xmlns:s="http://interlib.org/SDLIP/1.0#"
Both SDLIP and DASL allow any query types to be used in a search. However, the DASL specification requires every DASL-compliant service (client or server) to support the DAV:basicsearch query type. To facilitate interoperation between native DASL services and SDLIP/DASL services, we distinguish the following cases:
We discuss each case in turn.
Case 1) SDLIP client calls search method, passing a DAV:basicsearch query in the query parameter.
Case 1a) DAV:basicsearch query contains neither select nor from clause.
For example, assume that the SDLIP client invokes the following search request:
search(..., "<d:basicsearch><d:where>...</><d:orderby>...</></d:basicsearch>", ...):
This request causes the following XML structure to be sent to the server:
<d:searchrequest>
<d:basicsearch>
<d:select>...</>
<- inserted*
<d:from>...</>
<- inserted
<d:where>...</>
<- original*
<d:orderby>...</>
<- original
...
<s:clientSID>...</>
<- inserted
<s:stateTimeoutReq>...</> <- inserted
<s:queryOptions>...</>
<- inserted
</d:basicsearch>
</d:searchrequest>
*original: | if the information is present in the SDLIP search method's query parameter, it is copied from there into the DASL XML request structure |
*inserted: | the SDLIP/DASL transport module generates the element from information in the SDLIP search method's parameters and inserts it into the outgoing message |
SDLIP-specific elements (s:clientSID, s:stateTimeoutReq etc.) are inserted at the end of the d:basicsearch element.
Case 1b) SDLIP client specifies a complete DAV:basicsearch query (i.e. the query contains either DAV:select or DAV:from or both):
search(..., "<d:basicsearch><d:select>...</d:select>...</d:basicsearch>", ...):
In this case, the following XML structure is delivered over the wire:
<d:searchrequest>
<d:basicsearch>
<d:select>...</>
<- original
<d:from>...</>
<- original
<d:where>...</>
<- original
<d:orderby>...</>
<- original
...
<s:clientSID>...</>
<- inserted
<s:stateTimeoutReq>...</> <- inserted
<s:queryOptions>...</>
<- inserted
</d:basicsearch>
</d:searchrequest>
Case 2) SDLIP client uses a different query language (query schema), which is not DAV:basicsearch:
search(...., "<my:query>...</my:query>", ...)
Then the following XML structure is generated:
<d:searchrequest>
<s:SearchRequest>
<s:clientSID>...</>
<- inserted
<s:stateTimeoutReq>..</> <-
inserted
<s:subcols>...</>
<- inserted
<s:numDocs>...</>
<- inserted
<s:props>...</>
<- inserted
<s:queryOptions>...</>
<- inserted
<s:query>
<my:query>...</my:query> <-
original
</s:query>
</s:SearchRequest>
</d:searchrequest>
The rest of this section describes the translation between the XML structures used in the SDLIP search method and the XML structures used in the DASL protocol.
The subcols parameter of the search method is structured is follows:
<s:subcols>
<s:subcolName>[subcollection URL]</s:subcolName>*
<s:resSet>[server sessionID]</s:resSet>*
</s:subcols>
Thus, with SDLIP we can identify multiple subcollections and refer to the results of previous sessions. On the other hand, DASL allows us to specify at most one collection using a URL. In cases where SDLIP clients want to query multiple collections at once, the SDLIP/DASL mapping uses multiple DASL scope specifications. Naturally, native DASL servers may fail to answer such queries. Session IDs are encoded into URLs using a special prefix which allows server-side transport modules to distinguish them from regular collections. Of course, result set references are invalid for native DASL servers, since DASL servers are stateless. But SDLIP clients would know this because native DASL servers would not specify any state timeout. The timeout therefore always defaults to zero for DASL servers.
The content of the subcols parameter maps to the following d:from clause of d:basicsearch:
<d:from>
<d:scope><d:href>[subcollection URL]</d:href></d:scope>
<d:scope><d:href>http://interlib.org/SDLIP/1.0/SID#[server sessionID]</d:href></d:scope>
</d:from>
The docPropList parameter of the search method contains a list of properties to be retrieved:
<s:propList>
<dc:creator/>
<dc:title/>
...
</s:propList>
It is translated into the d:select clause:
<d:select>
<d:prop>
<dc:creator/>
<dc:title/>
...
</d:prop>
</d:select>
If no document properties are specified (i.e. docPropList is null or an empty XMLObject), the transport module assumes that all properties have to be delivered. Requests for all properties is expressed in DASL by a special tag d:allprop which is contained within the d:select clause. Thus, an empty property list maps onto the following DASL expression:
<d:select>
<d:allprop/>
</d:select>
If an SDLIP server receives a search request from a native DASL client, SDLIP-specific parameters are not present in the request. In this case, the search method of the server implementation is invoked by the server-side SDLIP/DASL transport module with the following default values (as specified in the SDLIP-Core specification):
For the DASL binding, the search results are delivered using the DAV:multistatus response format. The first d:response describes an SDLIP-specific URL and is used for delivering the s:stateTimeout and s:serverSID properties. Besides that, the sequence number of the document within the result set is included in every subsequent d:response. Since SDLIP delivers only properties that could be successfully retrieved, d:status of every document is set to "HTTP/1.1 200".
Below you see an outline of a DASL-encoded search result:
<d:multistatus>
<d:response> <d:href>http://interlib.org/SDLIP/1.0#SearchResult</d:href> <s:expectedTotal>...</s:expectedTotal> <s:stateTimeout>...</s:stateTimeout> <s:serverSID>...</s:serverSID> <d:response>
<d:response> <d:href>...</d:href> <d:propstat> <d:prop> <dc:title>Fighting a Wind Mill</dc:title> <dc:creator>Don Quichote</dc:creator> ... </d:prop> <d:status>HTTP/1.1 200</d:status> <s:DID>1</s:DID> </d:propstat> <d:response>
[<d:response>...</d:response>]*
</d:multistatus>
The DASL-encoded search result depicted above is delivered to the SDLIP client in the result parameter of the search method after the structure is converted to the required SDLIP format:
<s:SearchResult>
<s:doc>
<s:DID>1</s:DID>
<dc:title>Fighting a Wind Mill</dc:title>
<dc:creator>Don Quichote</dc:creator>
</s:doc>
...
[<s:doc>...</s:doc>]*
</s:SearchResult>
The first d:response element in the DASL XML result structure carries SDLIP-specific protocol information. It must not contain d:propstat, because otherwise it would be interpreted by native DASL clients as a regular set of search result document properties. Note that a URI (within the d:href element of every result) is an inherent property of every searchable resource in the DASL model. In contrast, SDLIP does not require retrieved documents to have an identifier that is valid outside the context of the result set. To make DASL's document URI property available to SDLIP clients, the SDLIP/DASL transport module treats the d:href property in a special way. If the client requested the property in the search request, and the server that processes the request is a native DASL server, then the transport module has to extract the d:href property and place it into the property list returned to the SDLIP client:
<s:SearchResult>
<s:doc>
<s:DID>1</s:DID>
<dc:title>Fighting a Wind Mill</dc:title>
<dc:creator>Don Quichote</dc:creator>
<d:href>...</d:href> <-- inserted by the transport module
</s:doc>
...
</s:SearchResult>
An SDLIP/DASL server may generate any valid URIs for the d:href elements given that they are unique within the result set.
If a search result is returned by a native DASL server, the SDLIP-specific parameters are not present in the search result. In this case the SDLIP/DASL transport module delivers the following default values to the SDLIP client:
Only those document properties are included into the result which have the d:status "HTTP/1.1 200". The sequence numbers (s:DID) become the ordinal numbers of the corresponding d:responses within the d:multistatus response.
If a native DASL server delivers a DASL error code 507 (Insufficient Storage) for some but not all of the requested
document properties, then the overall reply is interpreted by SDLIP clients as successful. The unsuccessful properties
will simply not be included in the result passed up to the SDLIP client application. Hence, SDLIP clients treat
DASL replies
HTTP/1.1 307 Multi-Status
and
HTTP/1.1 507 Insufficient Storage
equally (compare Exceptions).
If the search result delivered by a native DASL server does not contain any successfully retrieved properties (i.e. with the status "HTTP/1.1 200"), the client-side SDLIP transport module raises an exception NOT_FOUND_EXC (see Exceptions).
The semantics of SDLIP redirection differs from that of DASL. DASL requires the client to resend the original query. SDLIP assumes that the query execution starts and all subsequent invocations are performed on the delegate via the ResultAccess Interface.
Since the DASL protocol does not provide functionality similar to the ResultAccess Interface, a DASL client would not be able to meaningfully interact with an SDLIP server that implements ResultAccess. A search request sent by a native DASL client does not contain a timeout request, which defaults to zero. Thus, no state will be maintained on the SDLIP server and no redirection will ever be delivered back to the client.
If an SDLIP client specifies a positive timeout request, an SDLIP server may redirect subsequent requests. The list of delegates is packaged by the SDLIP/DASL transport module in the result set as follows:
HTTP/1.1 207 Multi-Status Content-type: text/xml Content-length: xxxx ... <d:multistatus>
<d:response> <d:href>http://interlib.org/SDLIP/1.0#SearchResult</d:href> <d:propstat> <d:prop> <s:expectedTotal>...</s:expectedTotal> <s:stateTimeout>...</s:stateTimeout> <s:serverSID>...</s:serverSID> <s:redirect> <s:serverDelegate>[URL_or_IOR_1]</s:serverDelegate> <s:serverDelegate>[URL_or_IOR_2]</s:serverDelegate> ... </s:redirect> </d:prop> </d:propstat> <d:response>
[<d:response>...</d:response>]* <-- regular result documents
</d:multistatus>
Upon receiving the above response from an SDLIP server the SDLIP client extracts the XML subtree identified by the s:redirect element and packs it into the SDLIP serverDelegate parameter of the search method:
<s:redirect>
<s:serverDelegate>[URL_or_IOR_1]</s:serverDelegate>
<s:serverDelegate>[URL_or_IOR_2]</s:serverDelegate>
...
</s:redirect>
A native DASL server redirects search requests as follows:
HTTP/1.1 400 Bad-Request
Content-Type: text/xml
Content-Length: xxxxx
...
<d:multistatus>
<d:response>
<d:href>[some URL]</d:href>
<d:status>HTTP/1.1 303 See Other</d:status>
<d:scopeerror/>
<d:redirectarbiter>[URL_1]</d:redirectarbiter>
<d:redirectarbiter>[URL_2]</d:redirectarbiter>
...
</d:response>
</d:multistatus>
(Note that the HTTP response contains error code 400). On detecting such a reply, the SDLIP/DASL transport module transparently resubmits the search request to one of [URL1], [URL2] etc. without interacting with the SDLIP client application.
This section summarizes the mappings of the methods used in the ResultAccess Interface. There are no equivalent operations in the DASL model. Consequently, a native DASL server will not respond to any of the following requests. Recall that SDLIP clients will not be tempted to make these requests to native DASL servers, because DASL servers will appear to SDLIP clients as stateless. On the other hand, stateful SDLIP servers will, of course, understand these methods.
Request mapping:
<s:getSessionInfo>
<s:serverSID>...</s:serverSID>
</s:getSessionInfo>
Response mapping:
<s:sessionInfo>
<s:expectedTotal>...</s:expectedTotal>
<s:stateTimeout>...</s:stateTimeout>
</s:sessionInfo>
Request mapping:
<s:getDocs>
<s:serverSID>...</s:serverSID>
<s:reqID> ...</s:reqID>
<s:propList>
<dc:title/>
<dc:creator/>
...
</s:propList>
<s:docSelection>1,3-5,7</s:docSelection>
</s:getDocs>
Response mapping (see Search Result)
Request mapping:
<s:extendStateTimeout>
<s:serverSID>...</s:serverSID>
<s:stateTimeoutReq>...</s:stateTimeoutReq>
</s:extendStateTimeout>
Response mapping:
<s:sessionInfo>
<s:stateTimeout>...</s:stateTimeout>
</s:sessionInfo>
Request mapping:
<s:cancelRequest>
<s:serverSID>...</s:serverSID>
<s:reqID>...</s:reqID>
</s:cancelRequest>
Response mapping: none or exception (see Exceptions)
Request mapping:
<s:removeDocs>
<s:serverSID>...</s:serverSID>
<s:docSelection>...</s:docSelection>
</s:removeDocs>
Response mapping: none or exception (see Exceptions)
This section describes the mapping of the SDLIP Metadata Interface methods. Similarly to the ResultAccess Interface, the Metadata Interface is an SDLIP-specific feature. If an SDLIP client attempts to invoke one of the following methods on a native DASL server, the latter will indicate failure with the status code 400 ("Bad Request") which raises SDLIP exception INVALID_REQUEST_EXC (see Exceptions).
Request mapping:
<s:getVersion/>
Response mapping (see the core document for the complete format description):
<s:SDLIPVersion>
...
</s:SDLIPVersion>
Request mapping:
<s:getSubcollectionInfo/>
Response mapping (see the core document for the complete format description):
<s:subcolInfo>
...
</s:subcolInfo>
Request mapping:
<s:getPropertyInfo>
<s:subcolName>...</s:subcolName>
</s:getPropertyInfo>
Response mapping (see the core document for the complete format description):
<s:propInfo>
...
</s:propInfo>
Exceptions are delivered in a format which is understandable both by DASL and SDLIP services. SDLIP servers may put additional SDLIP-specific information into DASL error messages:
HTTP/1.1 [DASL error condition]
...
<d:multistatus>
<d:response>
<d:href>http://interlib.org/SDLIP/1.0#exception</d:href>
<d:propstat>
<d:prop>
<my:stackTrace>...</my:stackTrace>
<my:threadDump>...</my:threadDump>
[...any further exception properties]
</d:prop>
</d:propstat>
<s:exceptionCode>400</s:exceptionCode>
<d:responsedescription>Murphy isn't sleeping...</d:responsedescription>
</d:response>
</d:multistatus>
The above example translates into the following SDLIP exception:
SDLIPException {
getCode() -> 400
getDescription() -> "Murphy isn't sleeping..."
getProps() -> "<s:propList><my:stackTrace>...[any
exception properties]"
}
If the exception was raised by a native DASL service, getDescription() still delivers the content of d:responsedescription; getProps() defaults to null, and getCode() is derived from the DASL error code is follows:
Note that DASL defines only three error conditions: 400 ("Bad request"), 422 ("Unprocessable Entity"), and 507 ("Insufficient Storage"). Therefore, an SDLIP server raising SDLIP exceptions maps them to DASL error codes as follows ("SDLIPException." prefix omitted):
The error condition 507 ("Insufficient Storage") delivered by a native DASL server is interpreted as a successful reply as long as at least one document property was successfully retrieved. Otherwise, NOT_FOUND_EXC is thrown.
If an SDLIP client attempts to call a method which is not implemented, the SDLIP/DASL transport module mapping should raise the NOT_IMPLEMENTED_EXC exception.
[DASL] | Saveen Reddy, Dale Lowry, Surenda Reddy, Rick Henderson, Jim Davis, Alan Babich: DAV Searching & Locating,
Internet Draft, June 3, 1999 http://www.webdav.org/dasl/protocol/draft-dasl-protocol-00.html |