Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Warning
titleRemoved in DSpace 6.0 (and above)

As of DSpace 6.0, the Lightweight Network Interface (LNI) is no longer provided with DSpace out-of-the-box.  However, the codebase is still available (in an unmaintained state) at https://github.com/DSpace/dspace-lni

If LNI is of importance to you or your institution, please get it touch, and we can work to provide you the "keys" to this old codebase.

Warning

NOTE: This page was copied from the old MoinMoin wiki and contains many markup artifacts and incorrect translations. Consult the the original page preserved here if you need precise answers about URI syntax, identifiers, etc.

...

Info
titleAbout the "prefix"

Prefix is the initial URL path at which the LNI service is "mounted" on its Web server. Since the LNI is intended
to be run out of a Java Servlet container such as Tomcat, possibly the same one running other DSpace services (e.g. the Web UI), it will probably be mounted under a separate initial path to distinguish its requests from those bound for other servlets. For example, on a server host "library.uni.edu", if the LNI is mounted at /dspace/dav, the complete prefix is http://library.uni.edu/dspace/davImage Removed.

The absolute path of the URI for each type of content object is composed as follows:

DSpace Site

/[prefix]/

Lookup handle

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="b234937c-b3c2-4ba7-9dd4-622878e3fb62"><ac:plain-text-body><![CDATA[

DSpace Site

/[prefix]/

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="9a506a7a-ab93-4dbe-b945-c19e55c2705c"><ac:plain-text-body><![CDATA[

Lookup handle

/[prefix]/lookup/handle/[handle] , /[prefix]/lookup/bitstream-handle/[sequence]/[handle]_

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="38318dc6-07b8-413d-b840-e3146d33da20"><ac:plain-text-body><![CDATA[

Community, Collection, Item (DSpace Objects)

/[prefix]/dso_[persistent-identifier]

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="f2305312-ccf6-43b0-8343-8998ee02e67e"><ac:plain-text-body><![CDATA[

Bitstream

/[prefix]/dso_[persistent-identifier]/bitstream_[pid]

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="05f63f06-65e4-43c5-bce2-186b05ae84cd"><ac:plain-text-body><![CDATA[

Workspace Items list

/[prefix]/workspace

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="d45f714a-efd9-4c1c-a0ec-34025894351e"><ac:plain-text-body><![CDATA[

Workspace Item

/[prefix]/workspace/wsi_db_[id]

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="f904e6b8-9abd-41d4-a7f8-5a6c024e6505"><ac:plain-text-body><![CDATA[

Workflow Items list

/[prefix]/workflow_own/ , /[prefix]/workflow_pool/

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="65e94745-fbfb-4537-ae83-1a58d2fa1508"><ac:plain-text-body><![CDATA[

Workflow Item

/[prefix]/workflow_own/wfi_db_[id]

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="53d38960-b78a-4b66-af66-b3c20b47c1d1"><ac:plain-text-body><![CDATA[

EPerson list

/[prefix]/eperson/

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="e7655d8e-b355-49f9-875c-5d8a7678700b"><ac:plain-text-body><![CDATA[

EPerson

/[prefix]/eperson/ep_db_[id]

]]></ac:plain-text-body></ac:structured-macro>

Key:

/lookup/handle/[handle] , /[prefix]/lookup/bitstream-handle/[sequence]/[handle]_

Community, Collection, Item (DSpace Objects)

/[prefix]/dso_[persistent-identifier]

Bitstream

/[prefix]/dso_[persistent-identifier]/bitstream_[pid]

Workspace Items list

/[prefix]/workspace

Workspace Item

/[prefix]/workspace/wsi_db_[id]

Workflow Items list

/[prefix]/workflow_own/ , /[prefix]/workflow_pool/

Workflow Item

/[prefix]/workflow_own/wfi_db_[id]

EPerson list

/[prefix]/eperson/

EPerson

/[prefix]/eperson/ep_db_[id]

Key:

  • [prefix] was covered above.
  • [persistent-identifier] is a specially-encoded version of the DSpace object's persistent identifier (such as a Handle). (See discussion of /lookup below for details).
  • [handle] is the Handle or other persistent identifier. It may only be used with the lookup service.
  • [pid] in the bitstream URI is a persistent bitstream identifier.
  • [id] is the numeric identifier of row in the database, used to identify e.g. an in-progress Item, such as a workflow or workspace
  • Wiki Markup
    \[prefix\] was covered above.
  • Wiki Markup
    \[persistent-identifier\] is a specially-encoded version of the DSpace object's persistent identifier (such as a Handle).  (See discussion of {{/lookup}} below for details).
  • Wiki Markup
    \[handle\] is the Handle or other persistent identifier. It may only be used with the {{lookup}} service.
  • Wiki Markup
    \[pid\] in the bitstream URI is a _persistent bitstream identifier_.
  • Wiki Markup\[id\] is the numeric identifier of row in the database, used to identify e.g. an in-progress Item, such as a workflow or workspace item.

About Identifiers

DSpace assigns "persistent identifiers", such as Handles, to all of its first-class content objects. The LNI's resource URIs do not contain literal DSpace identifiers, however, because some identifier formats contain characters (e.g. '/') which cause problems with existing WebDAV software, even when properly "escaped". To work around this problem and to prevent similar trouble with any new persistent identifier schemes adopted in the future, the LNI transforms an identifier by its own proprietary process before putting it into a resource URI. The exact transformation is not published so it can be changed without affecting clients.

...

Some example URIs:

Code Block

    Site          http://uni.edu/dspace/dav

    Lookup        http://uni.edu/dspace/dav/lookup/handle/1721.1/46
                  http://uni.edu/dspace/dav/lookup/handle/1721.1%2F46
                  http://uni.edu/dspace/dav/lookup/bitstream-handle/13/1721.1%2F46

    Community     http://uni.edu/dspace/dav/dso_1721.1$46

    Collection    http://uni.edu/dspace/dav/dso_1721.1$3549

    Item          http://uni.edu/dspace/dav/dso_1721.1$5543
                  http://uni.edu/dspace/dav/dso_1721.1$3549/dso_1721.1$5543

    Bitstream     http://uni.edu/dspace/dav/dso_1721.1$5543/bitstream_13
    Bitstream     http://uni.edu/dspace/dav/dso_1721.1$5543/bitstream_13.pdf

...

For example, the first URI visits all of the collections and communities in the whole Site, while the second only shows Collections under a given Community (avoiding sub-Communities):

Code Block

  http://uni.edu/dspace/dav/?type=COMMUNITY&type=COLLECTION

  http://uni.edu/dspace/dav/dso_1721.1$3549?type=collection

...

The general format of a GET URI is:

GET URI for Item:: *{{/}}\* _prefix_ \ *{{/}}\* _resource_path_ \ *{{?package=}}\* _package-format_ *_&other-packager-parameters{_}*
GET URI for Bitstream:: *{{/}}\* _prefix_ \ *{{/}}\* _resource_path_ _\[ .optional-extension \ ]_

Panel

Wiki Markup

Where prefix and the URI path are as described in the section above on Resource URIs.

...

Some examples of GET requests:

Code Block

    GET /dspace/dav/dso_1721.1$5543?package=METS&dmd=MODS

    GET /dspace/dav/dso_1721.1$5543/bitstream_13

    GET /dspace/dav/dso_1721.1$5543/bitstream_13.pdf

...

For example, to add a new item to the Collection at handle 1721.1/3549, we observe the following request and response:

Code Block

Request:    PUT /dspace/dav/dso_1721.1$3549?package=OCW-IMSCP
             ....package contents in body...

Response:   HTTP/1.1 201 OK
            Location: http://uni.edu/dspace/dav/dso_1721.1$F5549
             ....other headers....

...

The client makes inquiries about properties with the `PROPFIND` method, and the query itself is defined by the `propfind` XML element supplied
in the request body. For example, this query gets the `displayname` WebDAV property,
`dspace:type` (DSpace object type), and `getlastmodified` (the WebDAV last-modified time):

Code Block

<propfind xmlns="DAV:">
  <prop xmlns:dspace="http://www.dspace.org/xmlns/dspace">
    <displayname/>
    <getlastmodified/>
    <dspace:type/>
  </prop>
</propfind>

The result of a `PROPFIND` is a multistatus}}element, which contains the status (success/failure) of the query of each property on each resource, and the property values in `propstat` elements. This example returns successfully for the {{"displayname" and `dspace:type` properties, and fails to access the "getlastmodified" property:

Code Block

<multistatus xmlns="DAV:">
  <response>
    <href>/dspace/dav/dso_1721.1$5543</href>
    <propstat xmlns:dspace="http://www.dspace.org/xmlns/dspace">
      <prop>
        <displayname>Zen and the Art of Java Maintenance</displayname>
        <dspace:type>
          <dspace:item/>
        </dspace:type>
      </prop>
      <status>HTTP/1.1 200 OK</status>
    </propstat>
    <propstat>
      <prop>
        <getlastmodified/>
      </prop>
      <status>HTTP/1.1 403 Forbidden<status>
      <responsedescription>
      You do not have the right to read getlastmodified.
      </responsedescription>
    </propstat>
  </response>
</multistatus>

...

Here is an example that changes (or adds) the `displayname` property and removes `dspace:license`:

Code Block

<propertyupdate  xmlns="DAV:" xmlns:dspace="http://www.dspace.org/xmlns/dspace">
  <set>
    <prop>
      <displayname>Zen and the Art of Java Maintenance</displayname>
    </prop>
  </set>
  <remove>
    <prop>
      <dspace:license>
    </prop>
  </remove>
</propertyupdate>

...

  • dspace:submitter – ePerson resource of original submitter of this item.
  • dspace:owning_collection – persistent identifier (handle) of Collection that owns this item.
  • dspace:license – contents of license bitstream for this item, in a `<bitstream>` tag bitstream_xml (see below).
  • dspace:cc_license_text – text of Creative Commons license bitstream for this item, in a `<bitstream>` tag bitstream_xml (see below).
  • dspace:cc_license_rdf – RDF of Creative Commons license bitstream for this item, in a `<bitstream>` tag bitstream_xml (see below).
  • dspace:cc_license_url – URL of Creative Commons license for this item.
  • DAV:getlastmodified – This DAV property is assigned the DSpace last-modified date.
  • dspace:handle – the persistent identifier of this resource in URN format, e.g. `hdl:123.45/6789`.
  • dspace:withdrawn – `true` or `false`, indicating whether the Item has been withdrawn. This is the only property most users will have permission to read on a withdrawn Item.

Bitstream objects::

  • Wiki Markup{{DAV:getcontentlength}} -- value returned by bitstream's {{\[get Size\]}} – value returned by bitstream's getSize().
  • DAV:getcontenttype – mimetype from bistream's format.
  • NOTE: the DSpace object model has no notion of `getcontentlength` for Bitstreams, so we cannot offer it.
  • dspace:source – bitstream's source attribute.
  • dspace:description – bitstream's description attribute.unmigrated-wiki-markup
  • {{dspace:format}} -- formatbitstream's {{\[get Format\]getFormat().getID()}}.unmigrated-wiki-markup{{
  • dspace:format_description}} -- bitstream's {{\[get User Format Description\]}}.
  • Wiki Markup
    {{dspace:checksum}} -- bitstream's {{\[get Checksum\]()}}.
  • Wiki Markup
    {{dspace:checksum_algorithm}} -- bitstream's {{\[get Checksum Algorithm\]()}}.
  • – bitstream's getUserFormatDescription().
  • dspace:checksum – bitstream's getChecksum().
  • dspace:checksum_algorithm – bitstream's getChecksumAlgorithm().
  • dspace:sequence_id – returned by bitstream's getSequenceID() Wiki Markup{{dspace:sequence_id}} -- returned by bitstream's {{\[get Sequence ID\]}}.
  • dspace:bundle – name of bundle in which bitstream was created.
  • dspace:handle – the persistent identifier of this resource in URN format, e.g. `hdl:123.45/6789` (but usually not available for bitstreams (yet?))

...

  • dspace:submitter – EPerson resource of original submitter of this item.
  • dspace:collection – persistent identifier (handle) of Collection to which this item is being submitted.unmigrated-wiki-markup
  • {{dspace:has_multiple_files}} -- value of `\[has Multiple Files\]()` Wiki Markup{{ – value of hasMultipleFiles()
  • dspace:has_multiple_titles}} -- value of `\[has Multiple Titles\]()` – value of hasMultipleTitles()
  • Wiki Markup{{dspace:is_published_before}} -- value returned by `\[is Published Before\]()` – value returned by isPublishedBefore()
  • Every in-progress item also has one child resource which is a DSpace Item.

...

The `logo` attribute's value is a bitstream of an image. It is represented by the `dspace:bitstream` XML element, which gives the choice of encoding the bitstream as either a link (to an external resource) or inline base64-encoded data. The inline encoding should only be used for small (a few Kb) images. This example shows both alternatives:

Code Block

   <!-- link to external resource -->
   <dspace:bitstream>
     <dspace:link href="http://dspace.myuniv.edu/dspace/dav/retrieve_54321" />
   </dspace:bitstream>

   <!-- inline encoding -->
   <dspace:bitstream>
     <dspace:content contenttype="image/gif" contentlength="299" contentencoding="base64">
       ...text of base64-encoded data...
     </dspace:content>
   </dspace:bitstream>

...

NOTE: The SOAP servlet accepts WebDAV `GET` and `PUT` requests as well as SOAP messages, which simplifies the switching of modes in your
client code. Typically, you will start with a SOAP endpoint URL that looks something like http://uni.edu/dspace/lni/DSpaceLNIImage Removed. The final pathname element, DSpaceLNI, names a SOAP application within the servlet, so the servlet path is actually everything up to /dspace/lni/. To construct a WebDAV URL, simply use that servlet path as your WebDAV prefix, so e.g. a resource URL would become:
http://uni.edu/dspace/lni/dso_1721.1$5543Image Removed. There is a convenience method in the Java class LNIClientUtils to help manage this, but you will
have to implement it yourself for SOAP clients in other languages.

Note

Every feature of the LNI is available through WebDAV (HTTP); this API is provided for callers who prefer to use SOAP RPCs where possible.

Code Block

public class org.dspace.app.dav.client.LNISoapServlet {

  /**
  *** Returns Resource URI for the DSpace Object whose persistent
  *** identifier (i.e. Handle) is  "handle".  Optionally add Persistent ID
  *** (sequence ID) of a bitstream under the Item, if a URI to a bitstream
  *** is desired, otherwise bitstreamPID should be null.
  *** This does the same thing as the /lookup URI.
  ***/
  public String lookup(String handle, String bitstreamPID)
    throws java.rmi.RemoteException, org.dspace.app.dav.client.LNIRemoteException

  /**
  *** Same as PROPFIND WebDAV method.  "uri" may be relative to DSpace LNI
  *** prefix, or absolute; "propfind" is the propfind element, and depth is
  *** the content of the "Depth:" header.  Depth should be 0, 1, or the
  *** constant org.dspace.app.dav.client.LNIClientUtils.INFINITY (-1).
  *** Types is a comma-separated list of DSpace item types to which to
  *** restrict the query (see "type" option of PROPFIND method). May be null.
  *** Returns the multistatus document from the method's response.
  ***/
  public String propfind(String uri, Document propfind, int depth, String types)
    throws java.rmi.RemoteException, org.dspace.app.dav.client.LNIRemoteException

  /**
  *** Same as PROPPATCH WebDAV method.  "uri" may be relative to DSpace
  *** LNI prefix, or absolute; "propertyupdate" is the propertyupdate
  *** element.  Returns the multistatus document from the method's response.
  ***/
  public String proppatch(String uri, String propertyupdate)
    throws java.rmi.RemoteException, org.dspace.app.dav.client.LNIRemoteException

  /**
  *** Executes COPY method; "uri" and "destination_uri" may be relative
  *** to DSpace LNI prefix, or absolute.
  *** The depth and 'keepProperties' parameters correspond to
  *** parameters on the actual COPY WebDAV method, but DSpace ignores them
  *** at this time.
  *** The overwrite option will allow the copy to overwrite an existing
  *** resource if necessary.
  ***
  *** Returns the HTTP status code.
  ***/
  public int copy(String uri, String destination_uri, int depth,
                  boolean overwrite, boolean keepProperties)
    throws java.rmi.RemoteException, org.dspace.app.dav.client.LNIRemoteException
  }

  public class org.dspace.app.dav.client.LNIClientUtils {

  /** Depth of infinity in SOAP propfind() */
  public final static int INFINITY = -1;

  /**
  *** Make up a URL to access a WebDAV resource, given the SOAP "endpoint" URL
  *** and a relative URI such as is returned by lookup().  Clients should
  *** use this to obtain URLs to make HTTP GET and PUT requests.
  *** Packager may be null for a resource such as a Bitstream that does
  *** not require a packager.
  ***/
  public static URL makeDAVURL(String endpoint, String davURI, String packager);
    throws MalformedURLException

  /** alternate version that does not require packager. */
  public static URL makeDAVURL(String endpoint, String davURI);
    throws MalformedURLException

  /**
  *** Translates a WebDAV URL, such as would be returned by the PUT
  *** method, into a resource URI relative to the DAV root which can
  *** be passed to the SOAP methods.  Inverse of makeDAVURL.
  ***/
  public static String makeLNIURI(String endpoint, String davURL)
    throws MalformedURLException
  }

...

Here is an example of how a client would create a session and issue a `propfind` call with the LNI. It assumes the SOAP interface is built upon Apache's Axis SOAP implementation.

Code Block

  // DSpace credentials are either user/password in the URL, or X.509
  // client cert supplied with https: connection.
  String endpoint = "http://user:password@dspace.uni.edu/dspace/lni/DSpaceLNI";

  // get Axis locator
  LniSoapServletServiceLocator locator = new LniSoapServletServiceLocator();

  // create client endpoint
  LniSoapServle] lni = locator.getDSpaceLNI(new java.net.URL(endpoint));

  // get resource URI for known handle:
  String handle = "1234.56/789";
  String resourceUri = lni.lookup(handle, null);

  // get its properties..
  String result = lni.propfind(resourceUri,
        "<propfind xmlns=\"DAV:\"><allprop /></propfind>", 1);

  // ..now parse and display the XML in "result"..

...

Here is the document to send with the propfind request:

Code Block

   <propfind xmlns="DAV:">
     <prop xmlns:dspace="http://www.dspace.org/xmlns/dspace">
       <DAV:current_user_privilege_set />
     </prop>
   </propfind>

...

Model the Bitstream Format registry as one resource of the "collection" type. That top-level resource is just a container for the format records, so they can all be listed (e.g. by `PROPFIND`). The formats themselves are child resources of the Registry, named by the string returned by `get Short DescriptiongetShortDescription()` on the format.

  • The Registry URI is _/prefix_/format/
  • Each Bitstream Format's URI is _/prefix__/format/_short-description
  • `GET` is not implemented on any of these resources.
  • `PUT` of a new Bitstream Format URI creates it. The request body must be empty.
  • Bitstream Format resources have the following properties. They are all settable unless marked read-only.
    • `DAV:displayname` – same as description
    • `DAV:resourcetype` – empty. (`/format/` is a collection).
    • `dspace:type` – `<bitstream-format/>`
    • `description` – Full description of the bitstream format.
    • `extensions` – Comma-separated list of filename extensions associated with this format.
    • `ID` – READ-ONLY; internal database ID of this format.
    • `MIMEType` – Internet format type, aka MIME type, associated with this format. May not be unique amongst formats.
    • `support Level` – Support level, one of `UNKNOWN`, `KNOWN`, `SUPPORTED`.
    • `is Internal` – Is this format useed to store internal system information, rather than content? One of `TRUE`, `FALSE`.

Since the format resources are named by the "short description", it is a simple matter to find a format if you know the short description – just
compose the URI and make a `PROPFIND` request. Otherwise list all formats with a `PROPFIND` request of depth 1 on the parent collection, `/format/`.unmigrated-wiki-markup

It might be helpful to add query args to the `/format/` resource to search out formats, e.g. by filename extension. For example, the URI {{/format?\[find By Extension\]=pdf}} would return a `Location:` header redirecting to the format URI that has `pdf` among its extensions.

Other good Candidates for New Resource Types

...

9 pp. PDF showing schematic description of LNI Submit from MIT OpenCourseWare to MIT DSpace.

...

Complete PPT from which 9 pages above are extracted

  • http://dsug2006.uib.no/archive/reilly.ppt
    "Technical Introduction To and Initial Use Of the Lightweight Network Interface (LNI) (---to DSpace!)"It's rather difficult to post external link on this page.
    DSpace User Group Meeting, Bergen, Norway, April 2006

...