DAV implementation of an Information Service Repository

DAVRepository

Overview
Using DAV Repositories
Extending store item types
DAV Administrator requirements
Internals - How does it work?

Overview

com.sas.services.information.DAVRepository
The DAV Repository is a single persistent store for information used by client applications. It interfaces to a webDAV server to add, retrieve and update data. Repositories are defined in the Information Service configuration metadata (see example at the end).

Using DAV Repositories

To use a DAV repository, the Information Service must be able to connect to the repository. This can be done in a number of different ways.

  1. The DAV server is a configured server, with a Repository Definition (ReposDef) in the Information Service configuration, which specifies among other things the host, port, and base for the server and is autoconnected.
    <ReposDef name="Test" protocol="DAV" host="host" port="8100" base="davdir" domain="dept3" auto="true"/>
  2. The DAV server is a configured server, with a Repository Definition (ReposDef) in the Information Service configuration, and the global profile (personal or group) contains an attribute autoconnect for this repository
    <ReposDef name="Test" protocol="DAV" host="host" port="8100" base="davdir" domain="dept3" auto="false"/>
    and global profile has autoconnect=Test
  3. The DAV server is a configured server, with a Repository Definition (ReposDef) in the Information Service configuration, and the Information Service connectByName(UserContext, String) method is used to explicitly connect to the repository.
    RepositoryInterface r = is.connectByName(userContext, "Test");
  4. An explicit connection is made to the repository using the Information Service connect(UserContext, RepositoryDef) method
    RepositoryDef rdef = new ReposistoryDef("host", "8100", "dept3", "davdir", "DAV");
    RepositoryInterface r = is.connect(userContext, rdef);
A ReposDef may also indicate whether a proxy server or a secure connection is required. Specify a proxy attribute for a proxy server
<ReposDef name="Test" protocol="DAV" host="host" port="8100" base="davdir" domain="dept3" auto="false" proxy="http://proxyHost:proxyPort"/>
or use the setProxy method on the RepositoryDef object
RepositoryDef rdef = new ReposistoryDef("host", "8100", "dept3", "davdir", "DAV");
rdef.setProxy( "http://proxyHost:proxyPort" );

For HTTPS servers use the issecure property
<ReposDef name="Test" protocol="DAV" host="host" port="8100" base="davdir" domain="dept3" auto="false" issecure="true"/>
or use the setIsSecure method on the RepositoryDef object
RepositoryDef rdef = new ReposistoryDef("host", "8100", "dept3", "davdir", "DAV");
rdef.setIsSecure( true );

DAV Server URL

An HTTP server may only allow DAV support for a subset of the server's URL space. The relative path of this location is provided in the base parameter.

Example 1.
Let http://www.foo.com be an Apache2 web server, in which we have defined "Dav On" for the /davdir path. So, the url http://www.foo.com/davdir/ is the base DAV enabled URL. This information would break down as follows:
hostwww.foo.com
port80
basedavdir

Example 2.
Let http://www.foo.com:8080 is the URL for Slide server. The location for content storage in Slide would then be http://www.foo.com/slide/files and this would break down as follows:
hostwww.foo.com
port8080
baseslide/files

Credentials

Ensure that there is a credential set for the DAV server domain used. For example, if user "joe", password "smith" was associated with the domain "dept3", these credentials would be presented to the DAV server when any of the above methods is used to make a connection. Although credentials are not strictly required for servers with no authentication, this will prevent use of a personal repository for these users. So, even if authentication is not required define a credential set with a fake password.

DAVRepository is not a primary authentication repository and so the credential information must be located in the SAS Metadata Server or an LDAP repository. For the SAS Metadata Server, make sure that you have a login defined for the domain in which the repository is defined. For LDAP define a saslogin entry using the correct values for sasallowedclientdn, sasdomainname, sasloginname and sasuserpassword.

dn: saslogincn=DAVLogin,cn=saslogins,sasComponent=sasServer,cn=SAS,o=SAS Institute,c=US
sasloginname: joe
sasallowedclientdn: cn=Joe Smith,ou=People,o=SAS Institute,c=US
sasuserpassword: smith
sasreferencedn: cn=Joe Smith,ou=People,o=SAS Institute,c=US
sasminavail: 1
sasminsize: 1
objectclass: saslogin
sasdomainname: dept3
saslogincn: DAVLogin
saslogicalname: DAVLogical
description: Login to DAV server

Extending store item types

There are two main types in the repository, viz. container types and content types. The first step in adding a new type is to determine where to extend the type hierarchy. If there is a class that provides a good basis for your new type, then subclass it. If not, then subclass the base classes, viz. Folder and Content for smart objects, DAVFolder and DAVItem for DAV repository entities.

Defining a new DAV repository entity

Let's assume that we want to store text reports in the repository. We could have simply used the DAVItem class to create instances of generic content in the repository, but we would not be able to surface any report specific functionality through this class. So, let's create a subclass for these text reports, DAVReport. DAVReport will have content (the text of the report) and properties (metadata). We will define a new property type value {http://www.sas.com/rnd/itech/WebDAV}type=report. The factory will automatically creates instances of DAVReport for items with this type in the repository. (If the type had been "textreport" we would have had a DAVTextreport class).

Subclass DAVItem and change the object type to "report". This is all that is required for the factory to manufacture DAVReport items. Now new methods can be added to this class or to the smart object that will be based on this class.

Define additional properties to be stored with a report. All these properties should be associated with a namespace. Define a new namespace if one is required.

public static final String NS_WEBDAV_REPORT_URI = "http://example.org/xml/namespace/webdav.report-1.1";  
public class DAVReport extends DAVItem {
   ...
   String AUTHOR_PROPNAME = "{"+NS_WEBDAV_REPORT_URI+"}author";
   public DAVPackage( com.sas.services.information.Entity entity ) {
       super( entity );
       _objectClass = "report";
   }

   public DAVPackage( RepositoryInterface repos, String reposId ) {
      super( repos, reposId );
      _objectClass = "report";
   }

   public String getAuthor() {
      return getAttribute( AUTHOR_PROPNAME );
   }

   public void setAuthor( String author ) {
      return setAttribute( AUTHOR_PROPNAME, author );
   }
   ...
}

Defining a new smart object (metadata)

Now, one can go ahead and define a smart (metadata) object for reports. In order for the smart object to be returned from the repository, its type must be defined in the Information Service configuration metadata. Add the Type element for Report to the Factory element.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE InformationService>
<InformationService>
  ...
  <Repository protocol="DAV" class="com.sas.services.information.DAVRepository" />
  <ReposDef name="Server1" protocol="DAV" host="taylor" port="8200" base="dav" domain="taylor" auto="false" />
  ...
  <Factory>
    ...
    <Type protocol="dav" type="Report" action="ctor::com.sas.services.information.metadata.Report" />
    ...
  </Factory>
</InformationService>

Now implement the functionality of the Report class. As this class represents content, we have subclassed the Content class. Functionality added to the class will delegate to the repository entity for repository specific operations.

public class Report extends Content {
   ...
   public String getAuthor() {
      com.sas.services.information.metadata.dav.DAVReport d =
         (com.sas.services.information.metadata.dav.DAVReport)_repositoryObject;
      return d.getAuthor();
   }
   ...
}

Specifying administration login information

In some circumstances, it is necessary to have an administrator or super user to create user collections and assign the correct access control lists to these collections. The admin user and password can be set through the use of system properties. sysadmin.reposName and sysadminpw.reposName are the properties from which the administrator's userid and password will be obtained for the repository with name reposName. If these properties do not exist, sysadmin.dav and sysadminpw.dav will be used. If none of these properties are set, then the user collection creation and ACL settings are attempted with the principal making the request.

Internals - How does it work?

Here is an example of how a resource in the DAV store is brought into the Information Service.

The "type" property (actually this a SAS defined property in the "http://www.sas.com/rnd/itech/WebDAV" namespace) is used to determine the type or class of the entry in the store. If there isn't a type property or a corresponding class for this type cannot be found, then a default entity type will be used - DAVFolder for collections and DAVItem for non-collection resources.

The next stage uses the configuration metadata provided for the Information Service. This can be used to determine which class is instantiated to represent the smart object for the item in the store. Again, if there is no mapping (or a false mapping), then defaults are used - Folder for collections and Content for non-collection resources.

It makes sense that classes mapped for collections are subclasses of Folder, and classes mapped for non-collection resources are subclasses of Content. They can be direct or indirect subclasses.

Classes mentioned above are shortcuts for the following fully qualified class names: