package org.openxdm.xcap.common.appusage;
import java.io.IOException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Validator;
import org.openxdm.xcap.common.datasource.DataSource;
import org.openxdm.xcap.common.error.ConstraintFailureConflictException;
import org.openxdm.xcap.common.error.InternalServerErrorException;
import org.openxdm.xcap.common.error.SchemaValidationErrorConflictException;
import org.openxdm.xcap.common.error.UniquenessFailureConflictException;
import org.openxdm.xcap.common.uri.DocumentSelector;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
/**
* Each XCAP resource on a server is associated with an application. In
* order for an application to use those resources, application specific
* conventions must be specified. Those conventions include the XML
* schema that defines the structure and constraints of the data, well
* known URIs to bootstrap access to the data, and so on. All of those
* application specific conventions are defined by the application
* usage.
*
* @author Eduardo Martins
*
*/
public abstract class AppUsage {
/**
* Each application usage is associated with a name, called an
* Application Unique ID (AUID). This name uniquely identifies the
* application usage within the namespace of application usages, and is
* different from AUIDs used by other applications.
*/
private String auid = null;
/**
* All application usages MUST define a
* namespace URI that represents the default document namespace to be
* used when evaluating URIs. The default document namespace does not
* apply to elements or attributes within the documents themselves - it
* applies only to the evaluation of URIs within that application usage.
* Indeed, the term 'default document namespace' is distinct from the
* term 'default namespace'. The latter has the standard meaning within
* XML documents, and the former refers to the default used in
* evaluation of XCAP URIs. XCAP does not change in any way the
* mechanisms for determining the default namespace within XML
* documents. However, if a document contains a URI representing an
* XCAP resource, the default document namespace defined by the
* application usage applies to that URI as well.
*/
private String defaultDocumentNamespace = null;
/**
* The application usage MUST also identify the MIME type for documents
* compliant to that schema.
*/
private String mimetype = null;
private Validator uniquenessSchemaValidator = null;
/**
* All application usages MUST describe their document contents using XML
* schema. Here we have an appropriate validator.
*/
private Validator schemaValidator = null;
/**
* By default, each user is able to access (read, modify, and delete)
* all of the documents below their home directory, and any user is able
* to read documents within the global directory. However, only trusted
* users, explicitly provisioned into the server, can modify global
* documents.
* The application usage can specify a different authorization policy
* that applies to all documents associated with that application usage.
*/
private AuthorizationPolicy authorizationPolicy;
public AppUsage(String auid,String defaultDocumentNamespace,String mimetype,Validator schemaValidator) {
this.auid = auid;
this.defaultDocumentNamespace = defaultDocumentNamespace;
this.mimetype = mimetype;
this.schemaValidator = schemaValidator;
authorizationPolicy = new DefaultAuthorizationPolicy();
}
public AppUsage(String auid,String defaultDocumentNamespace,String mimetype,Validator schemaValidator, AuthorizationPolicy authorizationPolicy) {
this.auid = auid;
this.defaultDocumentNamespace = defaultDocumentNamespace;
this.mimetype = mimetype;
this.schemaValidator = schemaValidator;
this.authorizationPolicy = authorizationPolicy;
}
public AppUsage(String auid,String defaultDocumentNamespace,String mimetype,Validator schemaValidator,Validator uniquenessSchemaValidator) {
this.auid = auid;
this.defaultDocumentNamespace = defaultDocumentNamespace;
this.mimetype = mimetype;
this.schemaValidator = schemaValidator;
this.uniquenessSchemaValidator = uniquenessSchemaValidator;
authorizationPolicy = new DefaultAuthorizationPolicy();
}
public AppUsage(String auid,String defaultDocumentNamespace,String mimetype,Validator schemaValidator, Validator uniquenessSchemaValidator, AuthorizationPolicy authorizationPolicy) {
this.auid = auid;
this.defaultDocumentNamespace = defaultDocumentNamespace;
this.mimetype = mimetype;
this.schemaValidator = schemaValidator;
this.uniquenessSchemaValidator = uniquenessSchemaValidator;
this.authorizationPolicy = authorizationPolicy;
}
public String getDefaultDocumentNamespace() {
return defaultDocumentNamespace;
}
public String getAUID() {
return auid;
}
public String getMimetype() {
return mimetype;
}
public void validateSchema(Document document) throws SchemaValidationErrorConflictException, InternalServerErrorException {
// check arg
if (document == null) {
throw new IllegalArgumentException("document can't be null");
}
// validate
try {
if (schemaValidator != null) {
schemaValidator.validate(new DOMSource(document));
}
}
catch (SAXException e) {
throw new SchemaValidationErrorConflictException();
}
catch (IOException e) {
throw new InternalServerErrorException(e.getMessage());
}
}
public AuthorizationPolicy getAuthorizationPolicy() {
return authorizationPolicy;
}
/**
* The application usage can specify additional constraints that are not
* possible through XML Schema, e.g. a collection of documents need to have
* the root element with a unique value for attribute "id". In this method
* the app usage implements the checks on constraints for PUT operations. It
* is recommended that the main XML Schema of the app usage doesn't
* implement any of these checks, because in a error use case, the server
* will return a schema validation error, thus this API supports the usage
* of a additional XML Schema just for uniqueness contraints.
*
* @param document
* @param xcapRoot
* @param documentSelector
* @param dataSource
* @throws UniquenessFailureConflictException
* @throws InternalServerErrorException
* @throws ConstraintFailureConflictException
*/
public void checkConstraintsOnPut(Document document, String xcapRoot, DocumentSelector documentSelector, DataSource dataSource) throws UniquenessFailureConflictException, InternalServerErrorException, ConstraintFailureConflictException {
// check arg
if (document == null) {
throw new IllegalArgumentException("document can't be null");
}
else if(xcapRoot == null) {
throw new IllegalArgumentException("xcap root can't be null");
}
else if(documentSelector == null) {
throw new IllegalArgumentException("document selector can't be null");
}
else if(dataSource == null) {
throw new IllegalArgumentException("data source can't be null");
}
// validate uniqueness schema if exists
if (uniquenessSchemaValidator != null) {
try {
uniquenessSchemaValidator.validate(new DOMSource(document));
}
catch (SAXException e) {
throw new UniquenessFailureConflictException();
}
catch (IOException e) {
throw new InternalServerErrorException(e.getMessage());
}
}
// default is nothing else to check
}
/**
* The application usage may specify resource interdependencies, like one
* global document being a composition of all user documents, this method is
* where the application usage defines this dependency logic on PUT
* requests.
* @param document
* @param documentSelector
* @param dataSource
* @throws SchemaValidationErrorConflictException
* @throws UniquenessFailureConflictException
* @throws InternalServerErrorException
* @throws ConstraintFailureConflictException
*/
public void processResourceInterdependenciesOnPut(Document document, DocumentSelector documentSelector, DataSource dataSource) throws SchemaValidationErrorConflictException, UniquenessFailureConflictException, InternalServerErrorException, ConstraintFailureConflictException {
// check arg
if (document == null) {
throw new IllegalArgumentException("document can't be null");
}
else if(documentSelector == null) {
throw new IllegalArgumentException("document selector can't be null");
}
else if(dataSource == null) {
throw new IllegalArgumentException("data source can't be null");
}
//default is no resource interdependencies
}
/**
* The application usage can specify additional constraints that are not
* possible through XML Schema, e.g. a collection of documents need to have
* the root element with a unique value for attribute "id". In this method
* the app usage implements the checks on constraints for DELETE operations. It
* is recommended that the main XML Schema of the app usage doesn't
* implement any of these checks, because in a error use case, the server
* will return a schema validation error, thus this API supports the usage
* of a additional XML Schema just for uniqueness contraints.
*
* @param document
* @param xcapRoot
* @param documentSelector
* @param dataSource
* @throws UniquenessFailureConflictException
* @throws InternalServerErrorException
* @throws ConstraintFailureConflictException
*/
public void checkConstraintsOnDelete(Document document, String xcapRoot, DocumentSelector documentSelector, DataSource dataSource) throws UniquenessFailureConflictException, InternalServerErrorException, ConstraintFailureConflictException {
// check arg
if(xcapRoot == null) {
throw new IllegalArgumentException("xcap root can't be null");
}
else if(documentSelector == null) {
throw new IllegalArgumentException("document selector can't be null");
}
else if(dataSource == null) {
throw new IllegalArgumentException("data source can't be null");
}
// default is nothing else to check
}
/**
* The application usage may specify resource interdependencies, like one
* global document being a composition of all user documents, this method is
* where the application usage defines this dependency logic on DELETE
* requests.
*
* @param document
* @param documentSelector
* @param dataSource
* @throws SchemaValidationErrorConflictException
* @throws UniquenessFailureConflictException
* @throws InternalServerErrorException
* @throws ConstraintFailureConflictException
*/
public void processResourceInterdependenciesOnDelete(Document document, DocumentSelector documentSelector, DataSource dataSource) throws SchemaValidationErrorConflictException, UniquenessFailureConflictException, InternalServerErrorException, ConstraintFailureConflictException {
// check arg
if(documentSelector == null) {
throw new IllegalArgumentException("document selector can't be null");
}
else if(dataSource == null) {
throw new IllegalArgumentException("data source can't be null");
}
//default is no resource interdependencies
}
}