CMIS对象类型
- Repository必须支持的: cmis:document, cmis:folder
- Repository可能支持的: cmis:relationship, cmis:policy
- 可以从上述四个基本类型中扩展出子类型
- CMIS1.0不支持创建子类型,但可以读取子类型结构和定义
如何获取Document对象的类型定义
System.out.println("Getting type definition for doc type");
ObjectType objectType = session.getTypeDefinition(doc.getType().getId());
System.out.println("isBaseType() returns " + (objectType.isBaseType() ? "true" : "false"));
ObjectType baseType = objectType.getBaseType();
if (baseType == null) {
System.out.println("getBaseType() returns null");
} else {
System.out.println("getBaseType() returns " + baseType.getDisplayName());
}
ObjectType parentType = objectType.getParentType();
if (parentType == null) {
System.out.println("getParentType() returns null");
} else {
System.out.println("getParentType() returns " + parentType.getDisplayName());
}
System.out.println("Listing child types of " + objectType.getDisplayName());
for (ObjectType o : objectType.getChildren()) {
System.out.println("\t" + o.getDisplayName());
}
System.out.println("Getting immediate descendant types of " + objectType.getDisplayName());
for (Tree<ObjectType> o : objectType.getDescendants(1)) {
System.out.println("\t" + o.getItem().getDisplayName());
}
执行结果
Getting type definition for doc type
isBaseType() returns true
getBaseType() returns null
getParentType() returns null
Listing child types of CMIS Document
My Type 1 Level 1
My Type 2 Level 1
Complex type with properties, Level 1
Document type with properties, Level 1
VersionedType
Getting immediate descendant types of CMIS Document
My Type 1 Level 1
My Type 2 Level 1
Complex type with properties, Level 1
Document type with properties, Level 1
VersionedType
如何获取Document对象的属性
List<Property<?>> props = doc.getProperties();
for (Property<?> p : props) {
System.out.println(p.getDefinition().getDisplayName() + "=" + p.getValuesAsString());
}
执行结果
Is Latest Major Version=[false]
Content Stream Length=[26]
Content Stream Id=[store://2011/5/20/12/54/0d69ee48-ef03-4715-ae23-b84b4342315c.bin]
Version Series Checked Out By=[]
Object Type Id=[cmis:document]
Version Series Checked Out Id=[]
Name=[test.txt]
Content Stream MIME Type=[text/plain; charset=UTF-8]
Version series id=[workspace://SpacesStore/3cd2cbbf-1a00-4653-8ea8-1e91515c6092]
Creation Date=[Fri May 20 12:54:47 BST 2011]
Change token=[]
Version Label=[0.0]
Is Latest Version=[true]
Is Version Series Checked Out=[false]
Last Modified By=[admin]
Created by=[admin]
Checkin Comment=[]
Object Id=[workspace://SpacesStore/3cd2cbbf-1a00-4653-8ea8-1e91515c6092]
Is Immutable=[false]
Is Major Version=[false]
Base Type Id=[cmis:document]
Content Stream Filename=[test.txt]
Last Modified Date=[Fri May 20 12:54:47 BST 2011]
如何显式获取对象属性值
System.out.println("VersionLabel property on " + doc.getName() + " is "
+ doc.getVersionLabel());
System.out.println("Is this the latest version of " + doc.getName() + " ?: "
+ (doc.isLatestVersion() ? "yes" : "no"));
GregorianCalendar calendar = doc.getCreationDate();
String DATE_FORMAT = "yyyyMMdd";
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
System.out.println("Creation date of " + doc.getName() + " is " + sdf.format(calendar.getTime()));
如何根据属性ID获取属性对象
List<Property<?>> props = doc.getProperties();
Property<?> someProperty = props.get(0);
System.out.println(someProperty.getDisplayName() + " property on " + doc.getName()
+ " (by getPropertValue()) is "
+ doc.getPropertyValue(someProperty.getId()));
如何基于SQL-92语法查询CMIS对象
String query = "SELECT * FROM cmis:document WHERE cmis:name LIKE 'test%'";
ItemIterable<QueryResult> q = session.query(query, false);
// Did it work?
System.out.println("***results from query " + query);
int i = 1;
for (QueryResult qr : q) {
System.out.println("--------------------------------------------\n" + i + " , "
+ qr.getPropertyByQueryName("cmis:objectTypeId").getFirstValue() + " , "
+ qr.getPropertyByQueryName("cmis:name").getFirstValue() + " , "
+ qr.getPropertyByQueryName("cmis:createdBy").getFirstValue() + " , "
+ qr.getPropertyByQueryName("cmis:objectId").getFirstValue() + " , "
+ qr.getPropertyByQueryName("cmis:contentStreamFileName").getFirstValue() + " , "
+ qr.getPropertyByQueryName("cmis:contentStreamMimeType").getFirstValue() + " , "
+ qr.getPropertyByQueryName("cmis:contentStreamLength").getFirstValue());
i++;
}
cmis:document被称为虚拟表,cmis:name被称为虚拟列。
如何处理CMIS中的异常
Folder root = session.getRootFolder();
HashMap<String, String> newFolderProps = new HashMap<String, String>();
newFolderProps.put(PropertyIds.OBJECT_TYPE_ID, "cmis:folder");
newFolderProps.put(PropertyIds.NAME, "ADGFolderTest");
Folder folderTest = root.createFolder(newFolderProps);
Map<String, String> newFileProps = new HashMap<String, String>();
newFileProps.put(PropertyIds.OBJECT_TYPE_ID, "cmis:badtype");
newFileProps.put(PropertyIds.NAME, "ADGFileTest");
try {
folderTest.createDocument(newFileProps, null, VersioningState.MAJOR);
} catch (CmisObjectNotFoundException e) {
System.err.println("server error page :\n" + e.getErrorContent());
System.err.println("\nClient stack trace :\n");
e1.printStackTrace();
}
如果使用ATOMPUB绑定,可以从CmisBaseException.getErrorContent()得到服务器端的异常详情。
执行结果
server error page :
Apache Chemistry OpenCMIS - objectNotFound error
HTTP Status 404 - objectNotFound
[...]
Client stack trace :
org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException: Not Found
[...]
at org.apache.chemistry.opencmis.client.runtime.SessionImpl.createDocument(SessionImpl.java:651)
at org.apache.chemistry.opencmis.client.runtime.FolderImpl.createDocument(FolderImpl.java:87)
at org.apache.chemistry.opencmis.client.runtime.FolderImpl.createDocument(FolderImpl.java:409)
at org.apache.chemistry.opencmis.doc.TestingException.main(TestingException.java:104)
如何禁用对象缓存
OperationContext operationContext = session.createOperationContext();
operationContext.setCacheEnabled(false);
CmisObject object = session.getObject(id, operationContext);
如何获取Document对象的变体(Rendition)
OperationContext operationContext = session.createOperationContext();
operationContext.setRenditionFilterString("cmis:thumbnail");
CmisObject oo = session.getObject(o.getId(), operationContext);
List<Rendition> rl = oo.getRenditions();
如何获取从第5个元素开始的下一页CmisObject对象
OperationContext operationContext = session.createOperationContext();
operationContext.setMaxItemsPerPage(3);
ItemIterable<CmisObject> children1 = folderPaging.getChildren(operationContext);
int count = 0;
for (CmisObject child : children1.skipTo(5).getPage()) {
System.out.println("object " + count + " in page of " + children1.getPageNumItems() + " is " + child.getName());
count++;
}
如何实现翻页查看
System.out.println("Getting complete result set in pages of 3");
OperationContext operationContext = session.createOperationContext();
operationContext.setMaxItemsPerPage(3);
children1 = folderPaging.getChildren(operationContext);
int pageNumber = 0;
boolean finished = false;
count= 0;
while (!finished) {
ItemIterable<CmisObject> currentPage = children1.skipTo(count).getPage();
System.out.println("page " + pageNumber + " has " + currentPage.getPageNumItems() + " items");
for (CmisObject item : currentPage) {
System.out.println("object " + count + " is " + item.getName());
count++;
}
pageNumber++;
if (!currentPage.getHasMoreItems())
finished = true;
}
如何检测Repository支持CMIS规范的哪些能力(capabilities)
System.out.println("Printing repository capabilities...");
final RepositoryInfo repInfo = session.getRepositoryInfo();
RepositoryCapabilities cap = repInfo.getCapabilities();
System.out.println("\nNavigation Capabilities");
System.out.println("-----------------------");
System.out.println("Get descendants supported: " + (cap.isGetDescendantsSupported()?"true":"false"));
System.out.println("Get folder tree supported: " + (cap.isGetFolderTreeSupported()?"true":"false"));
System.out.println("\nObject Capabilities");
System.out.println("-----------------------");
System.out.println("Content Stream: " + cap.getContentStreamUpdatesCapability().value());
System.out.println("Changes: " + cap.getChangesCapability().value());
System.out.println("Renditions: " + cap.getRenditionsCapability().value());
System.out.println("\nFiling Capabilities");
System.out.println("-----------------------");
System.out.println("Multifiling supported: " + (cap.isMultifilingSupported()?"true":"false"));
System.out.println("Unfiling supported: " + (cap.isUnfilingSupported()?"true":"false"));
System.out.println("Version specific filing supported: " + (cap.isVersionSpecificFilingSupported()?"true":"false"));
System.out.println("\nVersioning Capabilities");
System.out.println("-----------------------");
System.out.println("PWC searchable: " + (cap.isPwcSearchableSupported()?"true":"false"));
System.out.println("PWC updatable: " + (cap.isPwcUpdatableSupported()?"true":"false"));
System.out.println("All versions searchable: " + (cap.isAllVersionsSearchableSupported()?"true":"false"));
System.out.println("\nQuery Capabilities");
System.out.println("-----------------------");
System.out.println("Query: " + cap.getQueryCapability().value());
System.out.println("Join: " + cap.getJoinCapability().value());
System.out.println("\nACL Capabilities");
System.out.println("-----------------------");
System.out.println("ACL: " + cap.getAclCapability().value());
System.out.println("End of repository capabilities");
如何检测Document对象上有哪些可执行Action
System.out.println("Getting the current allowable actions for the " + doc.getName() + " document object...");
for (Action a: doc.getAllowableActions().getAllowableActions()) {
System.out.println("\t" + a.value());
}
if (doc.getAllowableActions().getAllowableActions().contains(Action.CAN_CHECK_OUT)) {
System.out.println("can check out " + doc.getName());
} else {
System.out.println("can not check out " + doc.getName());
}
如何实现多档(Multi-filing)
if (!(cap.isMultifilingSupported())) {
System.out.println("Multifiling not supported by this repository");
} else {
// Add a new folder to the root folder
System.out.println("Creating 'ADGNewFolder 2' in the root folder");
Map<String, Object> newFolderProps = new HashMap<String, Object>();
newFolderProps.put(PropertyIds.OBJECT_TYPE_ID, "cmis:folder");
newFolderProps.put(PropertyIds.NAME, "ADGNewFolder 2");
newFolder2 = root.createFolder(newFolderProps);
System.out.println("Adding " + textFileName + "to 'ADGNewFolder 2' in the root folder");
doc.addToFolder(newFolder2, true);
// Did it work?
ItemIterable<CmisObject>children = newFolder.getChildren();
System.out.println("Now finding the following objects in the 'ADGNewFolder' folder:-");
for (CmisObject o : children) {
System.out.println(o.getName());
}
children = newFolder2.getChildren();
System.out.println("Now finding the following objects in the 'ADGNewFolder 2' folder:-");
for (CmisObject o : children) {
System.out.println(o.getName());
}
}
如何实现反多档(Unfiling)
if (!(cap.isUnfilingSupported())) {
System.out.println("Unfiling not supported by this repository");
} else {
// remove our document from both folders
System.out.println("removing :" + doc.getName() + "from 'ADGNewFolder':-");
doc.removeFromFolder(newFolder);
System.out.println("removing :" + doc.getName() + "from 'ADGNewFolder 2':-");
doc.removeFromFolder(newFolder2);
// Did it work?
Document docTest = (Document) session.getObject(id);
if (docTest != null) {
System.out.println(docTest.getName() + " still exists");
}
}
版本
- 只有文档对象才有版本特性
- 目录(Folder)和关系(Relationship)不支持版本
版本术语
- 版本序列(Version Series) - 每套版本序列拥有一个唯一的序列号
- 最新版本(Latest Version)
- 主版本(Major Version)
如何对文档进行check-out和check-in操作
- PWC(Private Working copy)
- Repositories可以只允许最新版本的Document被check-out,也可以允许所有版本check-out
- 支持服务器端PWC的Repository可以允许其他用户从服务端工作区中查看文档或搜索文档
- 只支持客户端PWC的Repository则不允许其他用户访问
if (versionable) {
Document pwc = (Document) session.getObject(doc.checkOut());
// default values if the document has no content
String filename = "version.txt";
String mimetype = "text/plain; charset=UTF-8";
String content = "";
// get the orginal content
ContentStream contentStream = doc.getContentStream();
if (contentStream != null) {
filename = contentStream.getFileName();
mimetype = contentStream.getMimeType();
content = getContentAsString(contentStream);
}
String updatedContents = content + "\nLine added in new version";
byte[] buf = updatedContents.getBytes("UTF-8");
ByteArrayInputStream input = new ByteArrayInputStream(buf);
contentStream = session.getObjectFactory().createContentStream(
filename, buf.length, mimetype, input);
// Check in the pwc
try {
pwc.checkIn(false, null, contentStream, "minor version");
} catch (CmisBaseException e) {
e.printStackTrace();
System.out.println("checkin failed, trying to cancel the checkout");
pwc.cancelCheckOut();
}
System.out.println("Document version history");
{
List<Document> versions = doc.getAllVersions();
for (Document version : versions) {
System.out.println("\tname: " + version.getName());
System.out.println("\tversion label: " + version.getVersionLabel());
System.out.println("\tversion series id: " + version.getVersionSeriesId());
System.out.println("\tchecked out by: "
+ version.getVersionSeriesCheckedOutBy());
System.out.println("\tchecked out id: "
+ version.getVersionSeriesCheckedOutId());
System.out.println("\tmajor version: " + version.isMajorVersion());
System.out.println("\tlatest version: " + version.isLatestVersion());
System.out.println("\tlatest major version: " + version.isLatestMajorVersion());
System.out.println("\tcheckin comment: " + version.getCheckinComment());
System.out.println("\tcontent length: " + version.getContentStreamLength()
+ "\n");
}
}
}
如何查询一棵文档树中的所有变体(Rendition)
if (session.getRepositoryInfo().getCapabilities().getRenditionsCapability()
.equals(CapabilityRenditions.NONE)) {
System.out.println("Repository does not support renditions");
} else {
System.out.println("Finding first object in repository with thumbnail renditions - start");
Folder node = root;
Stack<Folder> stack = new Stack<Folder>();
while (node != null) {
children = node.getChildren();
for (CmisObject o : children) {
if ((o.getType().isBaseType() && o.getType().getId().equals("cmis:folder"))
|| o.getBaseType().getId().equals("cmis:folder")) {
stack.push((Folder) o);
} else {
OperationContext context = session.createOperationContext();
context.setRenditionFilterString("cmis:thumbnail");
CmisObject oo = session.getObject(o.getId(), context);
List<Rendition> rl = oo.getRenditions();
if (!rl.isEmpty()) {
System.out.println("found " + o.getName() + " of type "
+ o.getType().getDisplayName() + "that has renditions...");
for (Rendition rendition : rl) {
System.out.print("kind: " + rendition.getKind());
System.out.print("\tmimetype: " + rendition.getMimeType());
System.out.print("\twidth: " + rendition.getWidth());
System.out.print("\theight: " + rendition.getHeight());
System.out.println("\tstream id: " + rendition.getStreamId());
}
break; // Just show the first object with
// renditions. Remove this
// Break to show them all
}
}
}
if (stack.isEmpty()) {
node = null;
} else {
node = (Folder) stack.pop();
}
}
System.out.println("Finding first object in repository with thumbnail renditions - end");
}
如何查询自定义子类型对象
if (session.getRepositoryInfo().getCapabilities().getQueryCapability()
.equals(CapabilityQuery.METADATAONLY)) {
System.out.println("Full search not supported");
} else {
String query = "SELECT * FROM ia:calendarEvent";
ItemIterable<QueryResult> queryResult = session.query(query, false);
for (QueryResult item : queryResult) {
System.out.println("Found "
+ item.getPropertyByQueryName("cmis:name").getFirstValue() + " of type "
+ item.getPropertyByQueryName("cmis:objectTypeId").getFirstValue());
System.out.println("property ia:descriptionEvent is "
+ item.getPropertyByQueryName("ia:descriptionEvent").getFirstValue());
System.out.println("property ia:toDate is "
+ item.getPropertyByQueryName("ia:toDate").getFirstValue());
System.out.println("property ia:fromDate is "
+ item.getPropertyByQueryName("ia:fromDate").getFirstValue());
}
}
关系Relationship
- 关系是有方向的,从source到target
- 非侵入式的,它并不修改source和target
- 关系也是有类型的,cmis:relationship
- 可以建立关系对象的有:document, folder, policy
- 关系自身不含有内容流(content stream)
- Repository对关系的支持不是必须的
如何创建关系
// Check if the repo supports relationships
ObjectType relationshipType = null;
try {
relationshipType = session.getTypeDefinition("cmis:relationship");
} catch (CmisObjectNotFoundException e) {
relationshipType = null;
}
if (relationshipType == null) {
System.out.println("Repository does not support cmis:relationship objects");
} else {
ObjectType cmiscustomRelationshipType = null;
try {
cmiscustomRelationshipType = session.getTypeDefinition("R:cmiscustom:assoc");
} catch (CmisObjectNotFoundException e) {
cmiscustomRelationshipType = null;
}
if (cmiscustomRelationshipType == null) {
System.out.println("Repository does not support R:cmiscustom:assoc objects");
} else {
System.out.println("Creating folders for relationships example");
newFolderProps = new HashMap<String, String>();
newFolderProps.put(PropertyIds.OBJECT_TYPE_ID, "cmis:folder");
newFolderProps.put(PropertyIds.NAME, "ADGFolderAssociations");
Folder folderAssociations = root.createFolder(newFolderProps);
newFileProps = new HashMap<String, String>();
newFileProps.put(PropertyIds.OBJECT_TYPE_ID, "D:cmiscustom:document");
newFileProps.put(PropertyIds.NAME, "ADGFileSource");
Document sourceDoc = folderAssociations.createDocument(newFileProps, null, VersioningState.MAJOR);
newFileProps.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document");
newFileProps.put(PropertyIds.NAME, "ADGFileTarget");
Document targetDoc = folderAssociations.createDocument(newFileProps, null, VersioningState.MAJOR);
Map<String, String> relProps = new HashMap<String, String>();
relProps.put("cmis:sourceId", sourceDoc.getId());
relProps.put("cmis:targetId", targetDoc.getId());
relProps.put("cmis:objectTypeId", "R:cmiscustom:assoc");
ObjectId relId = session.createRelationship(relProps, null, null, null);
System.out.println("created relationship");
}
}
如何检测关系适用的源对象和目标对象
RelationshipType relType = (RelationshipType) relationship.getType();
System.out.println(relType.getDisplayName()
+ "has the following allowed source types:");
for (ObjectType objectType : relType.getAllowedSourceTypes()) {
System.out.println("\t" + objectType.getDisplayName());
}
System.out.println(relType.getDisplayName()
+ "has the following allowed target types:");
for (ObjectType objectType : relType.getAllowedTargetTypes()) {
System.out.println("\t" + objectType.getDisplayName());
}
访问控制列表(Access Control List)
- Document对象的访问可以由ACL或者Policy进行控制
- ACL由ACE(Access Control Entry)构成
- CMIS预定义3种基本权限: [cmis:read, cmis:write, cmis:all]
每个ACE的构成有三部分
- 一个成员:包括用户、组、角色
- 一个或多个权限字段
- direct标志:true表示直接赋予,false表示经由继承得到
对于direct=false的ACE,你可以通过设置传播方式PROPOGATION来告知Repository如何处理子对象
OBJECTONLY
PROPOGATE
REPOSITORYDETERMINED
如何获取权限
System.out.println("getting ACL capabilities");
AclCapabilities aclCapabilities = session.getRepositoryInfo().getAclCapabilities();
System.out.println("Propogation for this repository is " + aclCapabilities.getAclPropagation().toString());
System.out.println("permissions for this repository are: ");
for (PermissionDefinition definition : aclCapabilities.getPermissions()) {
System.out.println(definition.toString());
}
System.out.println("\npermission mappings for this repository are: ");
Map<String, PermissionMapping> repoMapping = aclCapabilities.getPermissionMapping();
for (String key: repoMapping.keySet()) {
System.out.println(key + " maps to " + repoMapping.get(key).getPermissions());
}
如何给文档对象添加ACL
// Check if the repo supports ACLs
if (!session.getRepositoryInfo().getCapabilities().getAclCapability()
.equals(CapabilityAcl.MANAGE)) {
System.out.println("Repository does not allow ACL management");
} else {
System.out.println("Repository allows ACL management");
System.out.println("Creating folders for permissions example");
HashMap<String, String> newFolderProps = new HashMap<String, String>();
newFolderProps.put(PropertyIds.OBJECT_TYPE_ID, "cmis:folder");
newFolderProps.put(PropertyIds.NAME, "ADGFolderPermissions");
Folder folderAssociations = session.getRootFolder().createFolder(newFolderProps);
HashMap<String, String> newFileProps = new HashMap<String, String>();
ContentStream contentStream = new ContentStreamImpl("permissions.txt", null,
"plain/text", new ByteArrayInputStream("some content".getBytes()));
newFileProps.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document");
newFileProps.put(PropertyIds.NAME, "ADGFilePermissions");
Document testDoc = folderAssociations.createDocument(newFileProps, contentStream,
VersioningState.MAJOR);
OperationContext operationContext = new OperationContextImpl();
operationContext.setIncludeAcls(true);
testDoc = (Document) session.getObject(testDoc, operationContext);
System.out.println("ACL before adding an ace...");
for (Ace ace : testDoc.getAcl().getAces()) {
System.out.println("Found ace: " + ace.getPrincipalId() + " toString "+ ace.toString());
}
List<String> permissions = new ArrayList<String>();
permissions.add("cmis:write");
String principal = "admin";
Ace aceIn = session.getObjectFactory().createAce(principal, permissions);
List<Ace> aceListIn = new ArrayList<Ace>();
aceListIn.add(aceIn);
testDoc.addAcl(aceListIn, AclPropagation.REPOSITORYDETERMINED);
testDoc = (Document) session.getObject(testDoc, operationContext);
System.out.println("ACL after adding an ace...");
for (Ace ace : testDoc.getAcl().getAces()) {
System.out.println("Found ace: " + ace.getPrincipalId() + " toString "+ ace.toString());
}
}