eXo Platform 3.5

## Chapter 2. CMIS

This chapter will help you understand what CMIS is, how it is extended in WCM, and its features via the following topics:

- Overview

- CMIS specification

- xCMIS project

- CMIS features

- Service JARs

## 2.1. Overview

eXo Platform provides CMIS support using the xCMIS project and the WCM Storage provider.

About CMIS

The CMIS standard aims at defining a common content management web services interface that can be applied in content repositories and bring about the interoperability across repositories. The formal specification of CMIS standard is approved by the Organization for the Advancement of Structured Information Standards (OASIS) technical committee, who drives the development, convergence and adoption of global information society. With CMIS, enterprises now can deploy systems independently, and create specialized applications running over a variety of content management systems.

To see the advantages of content interoperability and the significance of CMIS as a whole, it is necessary to learn about mutual targets which caused the appearance of specification first.

- Content integration: With CMIS, integrating content among various repositories, even those created by different vendors in a single application, becomes faster, simpler and more effective. CMIS makes it possible for customers to integrate content management systems into their key business processes across business departments and vendor implementations.

- Access unification: CMIS enables different applications and manufacturers to be connected to a CMIS-enabled content repository simply. With CMIS, a business application's developer can focus on the application's business logic, rather than issues related to the compatibility or content migration.

About xCMIS

The xCMIS project, which is initially contributed to the Open Source community by eXo Platform, is an Open Source implementation of the Content Management Interoperability Services (CMIS) specification. xCMIS supports all the features stated in the CMIS core definition and both REST AtomPub and Web Services (SOAP/WSDL) protocol bindings.

### Tip

To learn more about xCMIS, visit:

- http://gazarenkov.blogspot.com/2010/01/xcmis1-cmis-in-nutshell.html

- http://code.google.com/p/xcmis/

About eXo CMIS

eXo CMIS is built on the top of xCMIS embedded in eXo Platform to expose the WCM drives as the CMIS repositories. The CMIS features are implemented as a set of components deployed on the eXo Container using XML files to describe the service configuration.

### Note

SOAP protocol binding is not implemented in eXo CMIS.

Figure: How eXo CMIS works

WCM drives exposure is implemented as a WCM storage provider to the xCMIS SPI. The storage provider uses mappings from the WCM's ManageDriveService to actual JCR nodes. AtomPub bindings makes WCM structure available via CMIS standard API.

## 2.2. CMIS specification

### Note

This is related to Content Management Interoperability Services (CMIS) Version 1.0 OASIS Standard 1 May 2010

http://en.wikipedia.org/wiki/Content_Management_Interoperability_Services

The CMIS interface is designed to be layered on top of existing Content Management systems and their existing programmatic interfaces. It is intended to expose all of the CM systems capabilities through the CMIS interfaces exhaustively. The CMIS specification defines the followings:

- A standard "domain model" for an ECM system - a set of core concepts included in all modern ECM systems, such as Object Types, properties, folders, documents, versions, and relationships; and a set of operations performed on those concepts, such as updating documents, or navigating via a folder hierarchy.

- The way to bind the CMIS domain model to two different web service protocols, including the Simple Object Access Protocol (SOAP) used in many ECM systems, and the Atom used in many Web 2.0 applications.

### Note

The SOAP protocol is not implemented in eXo CMIS.

The CMIS specification provides a Web services interface which can:

- Work over existing repositories, enabling customers to build and leverage applications against multiple repositories.

- Decouple Web services and content from the content management repository, enabling customers to manage content independently.

- Provide common Web services and Web 2.0 interfaces to dramatically simplify the application development.

- Build the development platform and language agnostic.

- Support the composite application development and mashups by the business or IT analysts.

## 2.3. xCMIS project

xCMIS includes the client side frameworks for integrating content from different enterprise repositories, according to CMIS standard.

The project is to make joining Enterprise Content repositories simpler by offering CMIS abilities and exposing them to language-independent CMIS clients via the most convenient protocol.

xCMIS project:

- Is embedded, packaged as the J2EE Web archive (WAR) and prepared "download and go" Tomcat bundle.

- Has a live demo with the full-featured CMIS Expert client, which is accessible via xcmis.org site and with prepared "download and go" Tomcat bundle (the client is accessible as the remote gadget).

- Is embedded in eXo Platform to create the special xCMIS jcr repository and access it with any CMIS client.

- Tested with third-party CMIS clients, such as IBM CMIS Firefox Connector and CMIS Spaces Flex+AIR client. Either local repository (as described here), or can be used as a CMIS repository's endpoint URL for these, or other types of clients.

Benefits of xCMIS:

- xCMIS is an open source, server side Java CMIS implementation, enabling to expose content in the existing content repositories according to the protocols defined in the CMIS specification.

- xCMIS will give developers a way to make their content repositories "pluggable" on the server side based on the internal Storage Provider Interface and additional protocol on-demand bindings.

- xCMIS will provide (several) CMIS client frameworks for repository-application and repository-repository interactions. The programming language and supported protocol can be selected by users. For example, the reasonable choice for using web applications, gadgets, and/or mashups is JavaScript, or GWT over REST AtomPub, while for inter-repository exchange, it may be Java over Web Services like WSDL/SOAP.

- Both the server and client sides of xCMIS are easily integrated in eXo Platform 3.0 infrastructure. In particular, xCMIS exposes the eXo JCR content repository and provides a framework for building web applications and gadgets for the GateIn portal.

The xCMIS project is distributed under the LGPL license. You can download sources on Google code, or visit Community Wiki for more information.

## 2.4. CMIS features

### 2.4.1. Integration with eXo WCM

eXo Web Content Management (WCM) system provides CMIS access to its content storage features:

- WCM drives

- Document files and folders

- Symlinks

- Categories

To expose WCM drives as CMIS repositories there is a special extension of CmisRegistry. Read the admin guide for the configuration of org.exoplatform.ecms.xcmis.sp.jcr.exo.DriveCmisRegistry component.

Work with CMIS is based on reference documents returned by services. Each CMIS service returns response containing links to other services describing the Document or operations on it. In most cases, a Document will be asked by its ID. Some services accepts a Document path.

### Note

Notes for use cases: To access the eXo CMIS services from the client side, use the Curl tool. The CMIS AtomPub binding which is based upon the Atom (RFC4287) and Atom Publishing Protocol (RFC5023) will be used.

SOAP binding is not implemented in eXo Platform 3.x.

#### JCR namespaces and nodetypes

CMIS uses special JCR namespaces cmis and xcmis internally.

To expose drives content following nodetypes supported:

- nt:file nodetype for representation of cmis:documents

- nt:folder for representation of cmis:folder

Since the CMIS specification does not allow having more root types except ones described above (cmis:documents and cmis:folder), those two (nt:file and nt:folder) are mapped to CMIS types.

There are two more nodetypes which are used: cmis:policy and cmis:relationship which represent CMIS types with corresponded (see Services description for details).

Additionally, nodetypes used in WCM are mapped as follow:

- nt:unstructured + extensions as cmis:folder

- exo:taxonomy + extensions as cmis:folder

In other words only nodetypes extending nt:file, nt:folder, nt:unstructured and exo:taxonomy will be exposed correctly via CMIS API.

### Warning

WCM's nodetype exo:article is not supported by eXo CMIS due to uncompliant structure to nt:file.

#### WCM drives as CMIS Repositories

The WCM drive is used to expose as an isolated repository via the CMIS service. Operations on the repository will reflect the drive immediately.

### Tip

When working with CMIS repositories, it is important to understand that a repository reflects a WCM Drive, which is a sub-tree in JCR workspace. Two or more drives can be mapped to a same workspace or a sub-tree. As a result, changes in one repository can affect others. Refer to the WCM drives mappings to know actual location of a content you will access or change.

##### Use Case: Browse Drives via getRepository

- Login to the website as a user with the developer role.

- Open Group | Sites Explorer, you can see the drives set of WCM, such as Sites Management, DMS Administration.

- Get the list of these WCM drives via CMIS using Curl, asking getRepositories service:

    curl -o getrepos.xml -u root:gtn http://localhost:8080/rest/private/cmisatom/

The requested file (getrepos.xml) contains the set of Repositories in the AtomPub format. The root element represents the set of workspaces representing WCM drives related to resources, for example, for DMS Administration, the response will contain data like:

       <service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/">

       <workspace>

          <atom:title type="text">DMS Administration</atom:title>

          <cmisra:repositoryInfo xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/">

             <cmis:repositoryId>DMS Administration</cmis:repositoryId>

             <cmis:repositoryName>DMS Administration</cmis:repositoryName>

          </cmisra:repositoryInfo>

          <collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/query">

             <atom:title type="text">Query</atom:title>

             <cmisra:collectionType>query</cmisra:collectionType>

          </collection>

          <collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/children/00exo0jcr0root0uuid0000000000000">

             <atom:title type="text">Folder Children</atom:title>

             <cmisra:collectionType>root</cmisra:collectionType>

          </collection>

          <collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/checkedout">

             <atom:title type="text">Checkedout collection</atom:title>

             <cmisra:collectionType>checkedout</cmisra:collectionType>

          </collection>

          <collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/unfiled">

             <atom:title type="text">Unfiled collection</atom:title>

             <cmisra:collectionType>unfiled</cmisra:collectionType>

          </collection>

          <collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/types">

             <atom:title type="text">Types Children</atom:title>

             <cmisra:collectionType>types</cmisra:collectionType>

          </collection>

          <cmisra:uritemplate>

             <cmisra:template>http://localhost:8080/rest/private/cmisatom/DMS%20Administration/object/{id}?filter={filter}&amp;includeAllowableActions={includeAllowableActions}&amp;includePolicyIds={includePolicyIds}&amp;includeRelationships={includeRelationships}&amp;includeACL={includeACL}&amp;renditionFilter={renditionFilter}

             </cmisra:template>

             <cmisra:type>objectbyid</cmisra:type>

             <cmisra:mediatype>application/atom+xml;type=entry</cmisra:mediatype>

          </cmisra:uritemplate>

          <cmisra:uritemplate>

             <cmisra:template>http://localhost:8080/rest/private/cmisatom/DMS%20Administration/objectbypath?path={path}&amp;filter={filter}&amp;includeAllowableActions={includeAllowableActions}&amp;includePolicyIds={includePolicyIds}&amp;includeRelationships={includeRelationships}&amp;includeACL={includeACL}&amp;renditionFilter={renditionFilter}

             </cmisra:template>

             <cmisra:type>objectbypath</cmisra:type>

             <cmisra:mediatype>application/atom+xml;type=entry</cmisra:mediatype>

          </cmisra:uritemplate>

          <cmisra:uritemplate>

             <cmisra:template>http://localhost:8080/rest/private/cmisatom/DMS%20Administration/query?q={q}&amp;searchAllVersions={searchAllVersions}&amp;maxItems={maxItems}&amp;skipCount={skipCount}&amp;includeAllowableActions={includeAllowableActions}=&amp;includeRelationships={includeRelationships}

             </cmisra:template>

             <cmisra:type>query</cmisra:type>

             <cmisra:mediatype>application/atom+xml;type=feed</cmisra:mediatype>

          </cmisra:uritemplate>

          <cmisra:uritemplate>

             <cmisra:template>http://localhost:8080/rest/private/cmisatom/DMS%20Administration/typebyid/{id}

             </cmisra:template>

             <cmisra:type>typebyid</cmisra:type>

             <cmisra:mediatype>application/atom+xml;type=entry</cmisra:mediatype>

          </cmisra:uritemplate>

       </workspace>

     </service>

Here are the collection of services and predefined templates which can be used from the client side to request resources related to this repository. For example, to get the WCM node of the DMS Administration drive by path, the objectbypath template can be used:

    http://localhost:8080/rest/private/cmisatom/DMS%20Administration/objectbypath?path={path}&amp;filter={filter}&amp;includeAllowableActions={includeAllowableActions}&amp;includePolicyIds={includePolicyIds}&amp;includeRelationships={includeRelationships}&amp;includeACL={includeACL}&amp;renditionFilter={renditionFilter}

where parameters include:

- Required:

  - ID repositoryId: The identifier for the repository.

  - String path: The path to the object.

- Optional:

  - String filter

  - Boolean includeAllowableActions

  - Enum includeRelationships

  - String renditionFilter

  - Boolean includePolicyIds

  - Boolean includeACL

### Note

Find full description of all specified services in the CMIS specification.

#### WCM Symlinks

Symlinks are used to organize the virtual access to documents in WCM, which is implemented like links in Unix/Linux/Mac OS (refer to ln command for more details).

### Note

JCR exo:symlink nodetype is used for such nodetypes.

Use Case: Follow Symlinks

1. Login to the ACME website as a user with the developer role.

2. Open Group --> Sites Explorer --> Sites Management, go to the folder /acme/documents.

3. Upload any file (for example test.txt) to /acme/documents.

4. Add this file to the acme/News category. It will create a symlink to /acme/documents/test.txt in /acme/categories/acme/News.

5. Get content of folder /acme/categories/acme/News via CMIS:

    curl -o news.xml -u root:gtn http://localhost:8080/rest/private/cmisatom/Managed%20Sites/objectbypath?path=/acme/categories/acme/News

The requested file (products.xml) contains the entry with information about the folder.

- The list of properties for the object (such as node Id or type).

- Allowable actions can be performed on the document; for example, requesting the children list.

- ACL and policies information.

    <entry xmlns="http://www.w3.org/2005/Atom" xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/">

       <id>f59a3539c0a80003625790bdadf566c5</id>

       <published>2010-09-09T18:11:57.707Z</published>

       <updated>2010-09-09T18:11:57.707Z</updated>

       <summary type="text"/>

       <author>

          <name>system</name>

       </author>

       <title type="text">News</title>

       <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites" rel="service" type="application/atomsvc+xml"/>

       <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f59a3539c0a80003625790bdadf566c5" rel="self"/>

       <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f59a3539c0a80003625790bdadf566c5" rel="edit"/>

       <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/typebyid/exo%3Ataxonomy" rel="describedby" type="application/atom+xml; type=entry"/>

       <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/allowableactions/f59a3539c0a80003625790bdadf566c5" rel="http://docs.oasis-open.org/ns/cmis/link/200908/allowableactions" type="application/cmis+xml; type=allowableActions"/>

       <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/relationships/f59a3539c0a80003625790bdadf566c5" rel="http://docs.oasis-open.org/ns/cmis/link/200908/relationships" type="application/atom+xml; type=feed"/>

       <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/policies/f59a3539c0a80003625790bdadf566c5" rel="http://docs.oasis-open.org/ns/cmis/link/200908/policies" type="application/atom+xml; type=feed"/>

       <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/objacl/f59a3539c0a80003625790bdadf566c5" rel="http://docs.oasis-open.org/ns/cmis/link/200908/acl" type="application/cmisacl+xml"/>

       <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/children/f59a3539c0a80003625790bdadf566c5" rel="down" type="application/atom+xml; type=feed"/>

       <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/descendants/f59a3539c0a80003625790bdadf566c5" rel="down" type="application/cmistree+xml"/>

       <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/foldertree/f59a3539c0a80003625790bdadf566c5" rel="http://docs.oasis-open.org/ns/cmis/link/200908/foldertree" type="application/atom+xml; type=feed"/>

       <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f59a3533c0a8000339af97059f243a25" rel="up" type="application/atom+xml; type=entry"/>

       <content type="text">News</content>

       <cmisra:object xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/">

          <cmis:properties>

             <cmis:propertyId displayName="cmis:allowedChildObjectTypeIds" localName="cmis:allowedChildObjectTypeIds" propertyDefinitionId="cmis:allowedChildObjectTypeIds" queryName="cmis:allowedChildObjectTypeIds"/>

             <cmis:propertyString displayName="cmis:path" localName="cmis:path" propertyDefinitionId="cmis:path" queryName="cmis:path">

                <cmis:value>/acme/categories/acme/News</cmis:value>

             </cmis:propertyString>

             <cmis:propertyId displayName="cmis:objectTypeId" localName="cmis:objectTypeId" propertyDefinitionId="cmis:objectTypeId" queryName="cmis:objectTypeId">

                <cmis:value>exo:taxonomy</cmis:value>

             </cmis:propertyId>

             <cmis:propertyString displayName="cmis:lastModifiedBy" localName="cmis:lastModifiedBy" propertyDefinitionId="cmis:lastModifiedBy" queryName="cmis:lastModifiedBy"/>

             <cmis:propertyString displayName="cmis:name" localName="cmis:name" propertyDefinitionId="cmis:name" queryName="cmis:name">

                <cmis:value>News</cmis:value>

             </cmis:propertyString>

             <cmis:propertyString displayName="cmis:createdBy" localName="cmis:createdBy" propertyDefinitionId="cmis:createdBy" queryName="cmis:createdBy"/>

             <cmis:propertyId displayName="cmis:objectId" localName="cmis:objectId" propertyDefinitionId="cmis:objectId" queryName="cmis:objectId">

                <cmis:value>f59a3539c0a80003625790bdadf566c5</cmis:value>

             </cmis:propertyId>

             <cmis:propertyDateTime displayName="cmis:creationDate" localName="cmis:creationDate" propertyDefinitionId="cmis:creationDate" queryName="cmis:creationDate"/>

             <cmis:propertyString displayName="cmis:changeToken" localName="cmis:changeToken" propertyDefinitionId="cmis:changeToken" queryName="cmis:changeToken"/>

             <cmis:propertyId displayName="cmis:baseTypeId" localName="cmis:baseTypeId" propertyDefinitionId="cmis:baseTypeId" queryName="cmis:baseTypeId">

                <cmis:value>cmis:folder</cmis:value>

             </cmis:propertyId>

             <cmis:propertyId displayName="cmis:parentId" localName="cmis:parentId" propertyDefinitionId="cmis:parentId" queryName="cmis:parentId">

                <cmis:value>f59a3533c0a8000339af97059f243a25</cmis:value>

             </cmis:propertyId>

             <cmis:propertyDateTime displayName="cmis:lastModificationDate" localName="cmis:lastModificationDate" propertyDefinitionId="cmis:lastModificationDate" queryName="cmis:lastModificationDate"/>

          </cmis:properties>

          <cmis:acl/>

          <cmis:exactACL>false</cmis:exactACL>

          <cmis:policyIds/>

          <cmis:rendition/>

       </cmisra:object>

    </entry>

To get the file which has been uploaded above, use the children service to get the list of child nodes of /acme/documents. Find this service URL in the response XML above:

    curl -o childs.xml -u root:gtn http://localhost:8080/rest/private/cmisatom/Managed%20Sites/children/f59a3539c0a80003625790bdadf566c5

In the requested file (childs.xml), find the entry related to test.txt file uploaded via the Sites Explorer. Search for the "test.txt" name by title.

       <entry xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/">

          <id>f708e208c0a80003554babb97bd934ba</id>

          <published>2010-09-09T18:06:31.987Z</published>

          <updated>2010-09-09T18:06:31.987Z</updated>

          <summary type="text"/>

          <author>

             <name>system</name>

          </author>

          <title type="text">test.txt</title>

          <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites" rel="service" type="application/atomsvc+xml"/>

          <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f708e208c0a80003554babb97bd934ba" rel="self"/>

          <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f708e208c0a80003554babb97bd934ba" rel="edit"/>

          <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/typebyid/cmis%3Adocument" rel="describedby" type="application/atom+xml; type=entry"/>

          <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/allowableactions/f708e208c0a80003554babb97bd934ba" rel="http://docs.oasis-open.org/ns/cmis/link/200908/allowableactions" type="application/cmis+xml; type=allowableActions"/>

          <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/relationships/f708e208c0a80003554babb97bd934ba" rel="http://docs.oasis-open.org/ns/cmis/link/200908/relationships" type="application/atom+xml; type=feed"/>

          <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/policies/f708e208c0a80003554babb97bd934ba" rel="http://docs.oasis-open.org/ns/cmis/link/200908/policies" type="application/atom+xml; type=feed"/>

          <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/objacl/f708e208c0a80003554babb97bd934ba" rel="http://docs.oasis-open.org/ns/cmis/link/200908/acl" type="application/cmisacl+xml"/>

          <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/versions/f708a0f1c0a8000333e3681f99fab760" rel="version-history" type="application/atom+xml; type=feed"/>

          <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f708e208c0a80003554babb97bd934ba?returnVersion=latest" rel="current-version" type="application/atom+xml; type=entry"/>

          <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/parents/f708e208c0a80003554babb97bd934ba" rel="up" type="application/atom+xml; type=feed"/>

          <link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/file/f708e208c0a80003554babb97bd934ba" rel="edit-media"/>

          <content src="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/file/f708e208c0a80003554babb97bd934ba" type="text/plain"/>

          <cmisra:object xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/">

             <cmis:properties>

                <cmis:propertyBoolean displayName="cmis:isLatestMajorVersion" localName="cmis:isLatestMajorVersion" propertyDefinitionId="cmis:isLatestMajorVersion" queryName="cmis:isLatestMajorVersion">

                   <cmis:value>false</cmis:value>

                </cmis:propertyBoolean>

                <cmis:propertyInteger displayName="cmis:contentStreamLength" localName="cmis:contentStreamLength" propertyDefinitionId="cmis:contentStreamLength" queryName="cmis:contentStreamLength">

                   <cmis:value>38</cmis:value>

                </cmis:propertyInteger>

                <cmis:propertyId displayName="cmis:contentStreamId" localName="cmis:contentStreamId" propertyDefinitionId="cmis:contentStreamId" queryName="cmis:contentStreamId">

                   <cmis:value>f708a0c2c0a800033bedeb35caddeed1</cmis:value>

                </cmis:propertyId>

                <cmis:propertyId displayName="cmis:objectTypeId" localName="cmis:objectTypeId" propertyDefinitionId="cmis:objectTypeId" queryName="cmis:objectTypeId">

                   <cmis:value>cmis:document</cmis:value>

                </cmis:propertyId>

                <cmis:propertyString displayName="cmis:versionSeriesCheckedOutBy" localName="cmis:versionSeriesCheckedOutBy" propertyDefinitionId="cmis:versionSeriesCheckedOutBy" queryName="cmis:versionSeriesCheckedOutBy"/>

                <cmis:propertyId displayName="cmis:versionSeriesCheckedOutId" localName="cmis:versionSeriesCheckedOutId" propertyDefinitionId="cmis:versionSeriesCheckedOutId" queryName="cmis:versionSeriesCheckedOutId"/>

                <cmis:propertyString displayName="cmis:name" localName="cmis:name" propertyDefinitionId="cmis:name" queryName="cmis:name">

                   <cmis:value>test.txt</cmis:value>

                </cmis:propertyString>

                <cmis:propertyString displayName="cmis:contentStreamMimeType" localName="cmis:contentStreamMimeType" propertyDefinitionId="cmis:contentStreamMimeType" queryName="cmis:contentStreamMimeType">

                   <cmis:value>text/plain</cmis:value>

                </cmis:propertyString>

                <cmis:propertyId displayName="cmis:versionSeriesId" localName="cmis:versionSeriesId" propertyDefinitionId="cmis:versionSeriesId" queryName="cmis:versionSeriesId">

                   <cmis:value>f708a0f1c0a8000333e3681f99fab760</cmis:value>

                </cmis:propertyId>

                <cmis:propertyDateTime displayName="cmis:creationDate" localName="cmis:creationDate" propertyDefinitionId="cmis:creationDate" queryName="cmis:creationDate">

                   <cmis:value>2010-09-09T18:06:31.987Z</cmis:value>

                </cmis:propertyDateTime>

                <cmis:propertyString displayName="cmis:changeToken" localName="cmis:changeToken" propertyDefinitionId="cmis:changeToken" queryName="cmis:changeToken"/>

                <cmis:propertyBoolean displayName="cmis:isLatestVersion" localName="cmis:isLatestVersion" propertyDefinitionId="cmis:isLatestVersion" queryName="cmis:isLatestVersion">

                   <cmis:value>true</cmis:value>

                </cmis:propertyBoolean>

                <cmis:propertyString displayName="cmis:versionLabel" localName="cmis:versionLabel" propertyDefinitionId="cmis:versionLabel" queryName="cmis:versionLabel">

                   <cmis:value>latest</cmis:value>

                </cmis:propertyString>

                <cmis:propertyBoolean displayName="cmis:isVersionSeriesCheckedOut" localName="cmis:isVersionSeriesCheckedOut" propertyDefinitionId="cmis:isVersionSeriesCheckedOut" queryName="cmis:isVersionSeriesCheckedOut">

                   <cmis:value>false</cmis:value>

                </cmis:propertyBoolean>

                <cmis:propertyString displayName="cmis:lastModifiedBy" localName="cmis:lastModifiedBy" propertyDefinitionId="cmis:lastModifiedBy" queryName="cmis:lastModifiedBy"/>

                <cmis:propertyString displayName="cmis:createdBy" localName="cmis:createdBy" propertyDefinitionId="cmis:createdBy" queryName="cmis:createdBy"/>

                <cmis:propertyString displayName="cmis:checkinComment" localName="cmis:checkinComment" propertyDefinitionId="cmis:checkinComment" queryName="cmis:checkinComment"/>

                <cmis:propertyId displayName="cmis:objectId" localName="cmis:objectId" propertyDefinitionId="cmis:objectId" queryName="cmis:objectId">

                   <cmis:value>f708e208c0a80003554babb97bd934ba</cmis:value>

                </cmis:propertyId>

                <cmis:propertyBoolean displayName="cmis:isImmutable" localName="cmis:isImmutable" propertyDefinitionId="cmis:isImmutable" queryName="cmis:isImmutable">

                   <cmis:value>false</cmis:value>

                </cmis:propertyBoolean>

                <cmis:propertyBoolean displayName="cmis:isMajorVersion" localName="cmis:isMajorVersion" propertyDefinitionId="cmis:isMajorVersion" queryName="cmis:isMajorVersion">

                   <cmis:value>false</cmis:value>

                </cmis:propertyBoolean>

                <cmis:propertyId displayName="cmis:baseTypeId" localName="cmis:baseTypeId" propertyDefinitionId="cmis:baseTypeId" queryName="cmis:baseTypeId">

                   <cmis:value>cmis:document</cmis:value>

                </cmis:propertyId>

                <cmis:propertyString displayName="cmis:contentStreamFileName" localName="cmis:contentStreamFileName" propertyDefinitionId="cmis:contentStreamFileName" queryName="cmis:contentStreamFileName">

                   <cmis:value>test.txt</cmis:value>

                </cmis:propertyString>

                <cmis:propertyDateTime displayName="cmis:lastModificationDate" localName="cmis:lastModificationDate" propertyDefinitionId="cmis:lastModificationDate" queryName="cmis:lastModificationDate">

                   <cmis:value>2010-09-09T18:06:31.987Z</cmis:value>

                </cmis:propertyDateTime>

             </cmis:properties>

             <cmis:acl/>

             <cmis:exactACL>false</cmis:exactACL>

             <cmis:policyIds/>

             <cmis:rendition/>

          </cmisra:object>

       </entry>

Then, get the test.txt file content via CMIS by using the file service and id of the file test.txt from childs.xml:

    curl -o test.txt -u root:gtn http://localhost:8080/rest/private/cmisatom/Managed%20Sites/file/f708e208c0a80003554babb97bd934ba

Get results in the test.txt file in the local folder. In this way, you will get file stored in the Sites Explorer to folder /acme/documents/test.txt via eXo CMIS by symlink path /acme/categories/acme/News/test.txt. As file's actual content referenced by id in CMIS, the path has no matter for content read or change.

#### Modify WCM via CMIS

### Note

Upload the modified local file using the command with id of the file stored in WCM (it is jcr:uuid of the file in JCR Workspace). Note that you should run this command from the folder where the local file is stored.

To update any file via CMIS, use the file service and the PUT request. Use the same file as in the previous use case (/acme/documents/test.txt, id:f708e208c0a80003554babb97bd934ba).

    curl -T test.txt -X PUT -H "Content-Type:text/plain; charset=UTF-8" -u root:gtn http://localhost:8080/rest/private/cmisatom/Managed%20Sites/file/f708e208c0a80003554babb97bd934ba

Go to the Sites Explorer to see changes applied from the local file in /acme/documents/test.txt.

#### CMIS search

CMIS provides a type-based query service for discovering objects that match specified criteria by defining a read-only projection of the CMIS data model into a Relational View.

CMIS query languages are based on a subset of the SQL-92 grammar. CMIS-specific language extensions to SQL-92 are called out explicitly. The basic structure of a CMIS query is a SQL statement that MUST include the following clauses:

- SELECT (virtual columns): This clause identifies the set of virtual columns that will be included in the query results for each row.

- FROM (Virtual Table Names): This clause identifies which Virtual Table(s) the query will run against.

Additionally, a CMIS query MAY include the following clauses:

- WHERE (conditions): This clause identifies the constraints that rows MUST satisfy to be considered a result for the query.

- ORDER BY (sort specification): This clause identifies the order in which the result rows MUST be sorted in the result row set.

Each CMIS ObjectType definition has the following query attributes:

Name | Description
--- | ---
query name (String) | Used for query operations on object types. In our SQL statement examples, all objecttypes is a queryName. For example, the given queryName matches the specific type of document. For example, in query like "SELECT * FROM cmis:document" ,"cmis:document" is queryName preconfigured in Document object type definition.
queryable (Boolean) | Indicate whether or not this object type is queryable. A non-queryable object type is not visible through the relational view that is used for query, and can not appear in the FROM clause of a query statement.
fulltextIndexed (Boolean) | Indicate whether objects of this type are full-text indexed for querying via the CONTAINS() query predicate.
includedInSupertypeQuery (Boolean) | Indicate whether this type and its subtypes appear in a query of this type's ancestor types. For example, if Invoice is a sub-type of Document, and its value is TRUE for a query on Document type, the matched instances of Invoice will be returned. If this attribute is FALSE, no instances (including matched ones) of Invoice will be returned.

Property definition also contains queryName and queryable attributes with the same usage.

##### Query examples

This section gives query examples for each specific case, including:

- Simple query

- Find document by several constraints

- Full-text search

- Extended full-text search

- Date property comparison

- Boolean property comparison

- IN Constraint

- Select all documents where longprop property is not in set

- Select all documents where longprop property is not in set

- INFOLDER constraint

- Select all documents that are in a specified folder

- Select all documents where query supertype is cmis:article

- INTREE constraint

- LIKE Comparison

- Test LIKE constraint with escape symbols

- NOT constraint

- Property existence

- ORDER BY

- ORDER BY ASC

- ORDER BY DESC

- ORDER BY SCORE (as columns)

- Not equal comparison (decimal)

- Not equal comparison (string)

- More than comparison (>)

###### Simple query

Query: Select all cmis:document.

    SELECT * FROM cmis:document

Query result:

- All documents from the Apollo program.

###### Find document by several constraints

Query: Select all documents where apollo:propertyBooster is 'Saturn V' and apollo:propertyCommander is Frank F. Borman, II or James A. Lovell, Jr.

Initial data:

- document1: apollo:propertyBooster - Saturn 1B, apollo:propertyCommander - Walter M. Schirra

- document2: apollo:propertyBooster - Saturn V, apollo:propertyCommander - Frank F. Borman, II

- document3: apollo:propertyBooster - Saturn V, apollo:propertyCommander - James A. Lovell, Jr.

    SELECT * FROM cmis:document WHERE apollo:propertyBooster = 'Saturn V' AND (apollo:propertyCommander = 'Frank F. Borman, II' OR  apollo:propertyCommander = 'James A. Lovell, Jr.')

Query result:

- document2 and document3.

###### Full-text search

Query: Select all documents that contains the "here" word.

Initial data:

- document1: content - "There must be test word"

- document2: content - "Test word is not here"

    SELECT * FROM cmis:document WHERE CONTAINS('here')

Query result:

- document2.

###### Extended full-text search

Query: Select all documents that contains "There must" phrase and do not contain the "check-word" term.

Initial data:

- document1: content - "There must be test word."

- document2: content - "Test word is not here. Another check-word."

- document3: content - "There must be check-word."

    SELECT * FROM cmis:document WHERE CONTAINS("There must" - "check-word")

Query result:

- document1.

###### Date property comparison

Query: Select all documents where cmis:lastModificationDate is more than 2007-01-01.

Initial data:

- document1: cmis:lastModificationDate - 2006-08-08

- document2: cmis:lastModificationDate - 2009-08-08

    SELECT * FROM cmis:document WHERE (cmis:lastModificationDate >= TIMESTAMP '2007-01-01T00:00:00.000Z')"

Query result:

- document2.

###### Boolean property comparison

Query: Select all documents where property apollo:someProperty equals to false.

Initial data:

- document1: apollo:someProperty - true

- document2: apollo:someProperty - false

    SELECT * FROM cmis:document WHERE (apollo:someProperty = FALSE)

Query result:

- document2.

###### IN Constraint

Query: Select all documents where apollo:propertyCommander is in set {'Virgil I. Grissom', 'Frank F. Borman, II', 'James A. Lovell, Jr.'}.

Initial data:

- document1: apollo:propertyCommander - Walter M. Schirra

- document2: apollo:propertyCommander - Frank F. Borman, II

- document3: apollo:propertyCommander - James A. Lovell, Jr.

- document4: apollo:propertyCommander - Eugene A. Cernan

    SELECT * FROM cmis:document WHERE apollo:propertyCommander IN ('Virgil I. Grissom', 'Frank F. Borman, II', 'James A. Lovell, Jr.')

Query result:

- document2, document3.

###### Select all documents where longprop property is not in set

Query: Select all documents where apollo:propertyCommander property is not in set {'Walter M. Schirra', 'James A. Lovell, Jr.'}.

Initial data:

- document1: apollo:propertyCommander - Walter M. Schirra

- document2: apollo:propertyCommander - Frank F. Borman, II

- document3: apollo:propertyCommander - James A. Lovell, Jr.

- document4: apollo:propertyCommander - Eugene A. Cerna

    SELECT * FROM cmis:document WHERE apollo:PropertyCommander NOT IN ('Walter M. Schirra', 'James A. Lovell, Jr.')

Query result:

- document2, document4.

###### Select all documents where longprop property is not in set

Query: Select all documents where apollo:propertyCommander_ property is not in set {'James A. Lovell, Jr.'}.

Initial data:

- document1: apollo:propertyCommander - Walter M. Schirra

- document2: apollo:propertyCommander - Frank F. Borman, II

- document3: apollo:propertyCommander - James A. Lovell, Jr.

- document4: apollo:propertyCommander - Eugene A. Cerna

    SELECT * FROM cmis:document WHERE  NOT (apollo:propertyCommander NOT IN ('James A. Lovell, Jr.'))

Query result:

- document3.

###### IN_FOLDER constraint

Query: Select all folders that are in folder1.

Initial data:

- folder1: id - 123456789

  - document1: Title - node1

- folder3:

  - folder4:

- folder2:

  - document2: Title - node2

    SELECT * FROM cmis:folder WHERE IN_FOLDER('123456789')

Query result:

- folder3.

###### Select all documents that are in a specified folder

Query: Select all documents that are in folder1.

Initial data:

- folder1: id - 123456789

  - document1: Title - node1

- folder2:

  - document2: Title - node2

    SELECT * FROM cmis:document WHERE IN_FOLDER('123456789')

Query result:

- document1.

###### Select all documents where query supertype is cmis:article

Initial data:

- testRoot: id - 123456789

- document1: Title - node1 typeID - cmis:article-sports

- document2: Title - node2 typeID - cmis:article-animals

    SELECT * FROM cmis:article WHERE IN_FOLDER('123456789')

Query result:

- document1, document2.

###### IN_TREE constraint

Query: Select all documents that are in the tree of folder1.

Initial data:

- folder1: id - 123456789

  - document1

- folder2:

  - document2

    SELECT * FROM cmis:document WHERE IN_TREE('123456789')

Query result:

- document1, document2.

###### LIKE Comparison

Query: Select all documents where apollo:propertyCommander begins with "James".

Initial data:

- document1: apollo:propertyCommander - Walter M. Schirra

- document2: apollo:propertyCommander - Frank F. James, II

- document3: apollo:propertyCommander - James A. Lovell, Jr.

- document4: apollo:propertyCommander - Eugene A. James

    SELECT * FROM cmis:document AS doc WHERE apollo:PropertyCommander LIKE 'James%'

Query result:

- document3.

###### Test LIKE constraint with escape symbols

Query: Select all documents where apollo:someProperty like 'ad%min%'.

Initial data:

- document1: Title - node1, apollo:someProperty - ad%min master

- document2: Title - node2, apollo:someProperty - admin operator

- document3: Title - node2, apollo:someProperty - radmin

    SELECT * FROM cmis:document AS doc WHERE apollo:someProperty  LIKE 'ad%min%'

Query result:

- document1.

###### NOT constraint

Query: Select all documents that do not contain the "world" word.

Initial data:

- document1: Title - node1, content - hello world

- document2: Title - node2, content - hello

    SELECT * FROM cmis:document WHERE NOT CONTAINS('world')

Query result:

- document2.

###### Property existence

Query: Select all documents that has apollo:propertyCommander property is NOT NULL.

Initial data:

- document1: apollo:propertyCommander - Walter M. Schirra

- document2: apollo:propertyCommander -

- document3: apollo:propertyCommander - James A. Lovell, Jr.

- document4: apollo:propertyCommander -

    SELECT * FROM cmis:document WHERE apollo:propertyCommander is NOT NULL

Query result:

- document1, document3.

###### ORDER BY

Query: Select all documents in default order (by document name).

Initial data:

- document1: Title - Apollo 7

- document2: Title - Apollo 8

- document3: Title - Apollo 13

- document4: Title - Apollo 17

    SELECT cmis:lastModifiedBy, cmis:objectId, cmis:lastModificationDate FROM cmis:document

Query result:

- document3, document4, document1, document2.

###### ORDER BY ASC

Query: Order by apollo:propertyCommander property value (in ascending order).

Initial data:

- document1: apollo:propertyCommander - Walter M. Schirra

- document2: apollo:propertyCommander - Frank F. Borman, II

- document3: apollo:propertyCommander - James A. Lovell, Jr.

- document4: apollo:propertyCommander - Eugene A. Cerna

    SELECT cmis:lastModifiedBy, cmis:objectId, cmis:lastModificationDate FROM cmis:document ORDER BY apollo:propertyCommander

Query result:

- document4, document2, document3, document1.

###### ORDER BY DESC

Query: Order by apollo:propertyCommander property value (in descending order).

Initial data:

- document1: apollo:propertyCommander - Walter M. Schirra

- document2: apollo:propertyCommander - Frank F. James, II

- document3: apollo:propertyCommander - James A. Lovell, Jr.

- document4: apollo:propertyCommander - Eugene A. James

    SELECT cmis:lastModifiedBy, cmis:objectId, cmis:lastModificationDate FROM cmis:document ORDER BY cmis:propertyCommander DESC

Query result:

- document1, document3, document2, document4.

###### ORDER BY SCORE (as columns)

Query: Select all documents which contains word "moon" ordered by score.

Initial data:

- document1: content - "Earth-orbital mission, the first manned launch"

- document2: content - "from another celestial body - Earth's Moon"

- document3: content - "NASA intended to land on the Moon, but a mid-mission technical"

- document4: content - "It was the first night launch of a U.S. human"

    SELECT cmis:lastModifiedBy, cmis:objectId, cmis:lastModificationDate FROM cmis:document WHERE CONTAINS('moon') ORDER BY SCORE()

Query result:

- document2, document3.

###### Not equal comparison (decimal)

Query: Select all documents which have apollo:propertyBooster peroperty that does not equal to 3.

Initial data:

- document1: Title - node1, apollo:propertyBooster - 3

- document2: Title - node2, apollo:propertyBooster - 15

    SELECT * FROM cmis:document WHERE apollo:propertyBooster <> 3

Query result:

- document2.

###### Not equal comparison (string)

Query: Select all documents property apollo:someProperty that does not equals to "test word second".

Initial data:

- document1: apollo:someProperty - "test word first"

- document2: apollo:someProperty - "test word second"

    SELECT * FROM cmis:document WHERE apollo:someProperty <> 'test word second'

Query result:

- document1.

###### More than comparison (>)

Query: Select all documents wihch have apollo:propertyBooster property which is more than 5.

Initial data:

- document1: apollo:propertyBooster - 3

- document2: apollo:propertyBooster - 15

    SELECT * FROM cmis:document WHERE apollo:propertyBooster > 5

Query result:

- document2.

The CMIS specification prescribes:

- Domain model

- Services

### 2.4.2. CMIS Domain Model

The CMIS Domain Model defines a repository as a container and an entry point to the objects that is quite simple and non-restrictive. The followings are some of the common entities of the domain model.

- Repository is a container of objects with a set of "capabilities" which may be different depending on the implementation.

- Object is the entity managed by a CMIS repository.

- Object Type is a classification related to an object. It specifies a fixed and non-hierarchical set of properties ("schema") that all objects of that type have.

- Document Object is an elementary information entity.

- Folder Object is a collection of fileable objects.

- Relationship Object is used to describe a dependent object semantically.

- Policy Object represents an administrative policy applied to an object.

- Access Object defines permissions.

- Versioning is to support versioning for Document objects.

- Query is type-based in a simplified SQL SELECT statement.

- Change Log is a mechanism which enables applications to discover changes to the objects stored.

### Note

CMIS specifies a query language based on the SQL-92 standard, plus the extensions, in conjunction with the model mapping defined by the CMIS's relational view.

All objects are classified by an Object Type which declares that all objects of the given type have some sets of properties in common. Each property consists of a set of attributes, such as the TypeID, the property ID, its display name, its query name, and more. There are only four base types, including Document, Folder, Relationship, and Policy. Also, you can extend those basic types by modifying a set of their properties.

Document Object and Folder Object are self-explanatory. Document Object has properties to hold document metadata, such as the document author, modification date and custom properties. It can also contain a content stream whether it is required, and renditions, such as a thumbnail view of document. Folder is used to contain objects. Apart from the default hierarchical structure, CMIS can optionally store objects in multiple folders or in no folders at all (so-called multifiling and unfiling capabilities). Relationship Object denotes the connection between two objects (target and source). An object can have multiple relationships with other objects. Policy Object is a way to define administrative policies in managing objects. For example, you can use a CMIS policy to define which documents are subject to retention policies.

### 2.4.3. CMIS Services

CMIS provides a set of services to access and manage the content or repository. These services include:

Name | Description
--- | ---
Repository Services | Discover information about the repository and the object types defined for the repository.
Navigation Services | Traverse the folder hierarchy in a CMIS repository, and to locate documents which are checked out.
Object Services | Execute ID-based CRUD functions (Create, Retrieve, Update, Delete) on objects in a repository.
Multi-filing Services (optional) | Put an object in more than one folder (multi-filing), or outside the folder hierarchy (unfiling).
Discovery Services | Search for queryable objects in a repository.
Versioning Services | Check out, navigate to documents, or update a Document Version Series (checkOut, cancelCheckOut, getPropertiesOfLatestVersion, getAllVersions, deleteAllVersions).
Relationship Services (optional) | Retrieve an object for its relationships.
Policy Services (optional) | Apply, remove, or query for policies.
ACL Services | Return and manage the Access Control List (ACL) of an object. ACL Services are not supported by all repositories.

Some repositories might not implement certain optional capabilities, but they are still considered as CMIS-compliant. Each service has binding which defines the way messages will be serialized and wired. Binding is based on HTTP and uses the Atom Publishing Protocol.

## 2.5. Service JARs

### Note

JCRs are listed below for the informational purpose only. For example, if the customer application needs to use the same third-parties used by eXo CMIS but with another version. All files are delivered in eXo Platform 3.5 distribution.

eXo CMIS consists of JAR files below:

xCMIS project files (for xCMIS 1.2.x)

- xcmis-renditions-X.X.X.jar

- xcmis-restatom-X.X.X.jar

- xcmis-search-model-X.X.X.jar

- xcmis-search-parser-cmis-X.X.X.jar

- xcmis-search-service-X.X.X.jar

- xcmis-spi-X.X.X.jar

eXo WCM Storage Provider for xCMIS SPI (uses the same version as the WCM/ECMS system)

- exo-ecms-ext-xcmis-sp-Y.Y.Y.jar

Third-party dependencies (for xCMIS 1.2.x)

- abdera-client-0.4.0-incubating.jar

- abdera-core-0.4.0-incubating.jar

- abdera-i18n-0.4.0-incubating.jar

- abdera-parser-0.4.0-incubating.jar

- abdera-server-0.4.0-incubating.jar

- antlr-runtime-3.1.3.jar

- axiom-api-1.2.5.jar

- axiom-impl-1.2.5.jar

- jaxen-1.1.1.jar

- lucene-regex-2.4.1.jar

Copyright © 2009-2012. All rights reserved. eXo Platform SAS