diff --git a/config/alfresco/audit/alfresco-audit-cmis.xml b/config/alfresco/audit/alfresco-audit-cmis.xml
new file mode 100644
index 0000000000..030aa697fb
--- /dev/null
+++ b/config/alfresco/audit/alfresco-audit-cmis.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config/alfresco/opencmis-context.xml b/config/alfresco/opencmis-context.xml
index b5fc0ab44a..8561513ca9 100644
--- a/config/alfresco/opencmis-context.xml
+++ b/config/alfresco/opencmis-context.xml
@@ -208,11 +208,13 @@
+
\ No newline at end of file
diff --git a/source/java/org/alfresco/opencmis/CMISChangeLogDataExtractor.java b/source/java/org/alfresco/opencmis/CMISChangeLogDataExtractor.java
index e97919a38d..7b20fb7bc4 100644
--- a/source/java/org/alfresco/opencmis/CMISChangeLogDataExtractor.java
+++ b/source/java/org/alfresco/opencmis/CMISChangeLogDataExtractor.java
@@ -22,7 +22,6 @@ import java.io.Serializable;
import java.util.HashMap;
import org.alfresco.opencmis.dictionary.CMISDictionaryService;
-import org.alfresco.opencmis.dictionary.CMISPropertyAccessor;
import org.alfresco.opencmis.dictionary.TypeDefinitionWrapper;
import org.alfresco.repo.audit.extractor.AbstractDataExtractor;
import org.alfresco.service.cmr.model.FileInfo;
@@ -30,7 +29,6 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
-import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
/**
@@ -46,6 +44,7 @@ public class CMISChangeLogDataExtractor extends AbstractDataExtractor
private NodeService nodeService;
private CMISDictionaryService cmisDictionaryService;
+ private CMISConnector cmisConnector;
/**
* Extracts relevant node refs and Ids from auditing data
@@ -57,15 +56,10 @@ public class CMISChangeLogDataExtractor extends AbstractDataExtractor
{
NodeRef nodeRef = getNodeRef(value);
- QName typeQName = nodeService.getType(nodeRef);
- TypeDefinitionWrapper type = cmisDictionaryService.findNodeType(typeQName);
-
HashMap result = new HashMap(5);
result.put(KEY_NODE_REF, nodeRef);
- // Support version nodes by recording the object ID
- CMISPropertyAccessor accessor = type.getPropertyById(PropertyIds.OBJECT_ID).getPropertyAccessor();
- result.put(KEY_OBJECT_ID, accessor.getValue(accessor.createNodeInfo(nodeRef)));
-
+ result.put(KEY_OBJECT_ID, cmisConnector.createObjectId(nodeRef, true));
+
return result;
}
@@ -125,4 +119,8 @@ public class CMISChangeLogDataExtractor extends AbstractDataExtractor
{
this.cmisDictionaryService = cmisDictionaryService;
}
+
+ public void setCmisConnector(CMISConnector cmisConnector) {
+ this.cmisConnector = cmisConnector;
+ }
}
diff --git a/source/java/org/alfresco/opencmis/CMISConnector.java b/source/java/org/alfresco/opencmis/CMISConnector.java
index b844d68d1a..637e1b5223 100644
--- a/source/java/org/alfresco/opencmis/CMISConnector.java
+++ b/source/java/org/alfresco/opencmis/CMISConnector.java
@@ -1170,9 +1170,14 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
* be the assocRef guid.
*/
public String constructObjectId(AssociationRef assocRef, String versionLabel)
+ {
+ return constructObjectId(assocRef, versionLabel, isPublicApi());
+ }
+
+ public String constructObjectId(AssociationRef assocRef, String versionLabel, boolean dropStoreRef)
{
StringBuilder sb = new StringBuilder(CMISConnector.ASSOC_ID_PREFIX);
- if(isPublicApi())
+ if(dropStoreRef)
{
// always return the guid
sb.append(assocRef.getId());
@@ -1204,9 +1209,14 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
* be the node guid.
*/
public String constructObjectId(String incomingNodeId, String versionLabel)
+ {
+ return constructObjectId(incomingNodeId, versionLabel, isPublicApi());
+ }
+
+ public String constructObjectId(String incomingNodeId, String versionLabel, boolean dropStoreRef)
{
StringBuilder sb = new StringBuilder();
- if(isPublicApi())
+ if(dropStoreRef)
{
// always return the guid
sb.append(getGuid(incomingNodeId));
@@ -1264,9 +1274,14 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
* be the incomingNodeRef guid.
*/
public String constructObjectId(NodeRef incomingNodeRef, String versionLabel)
+ {
+ return constructObjectId(incomingNodeRef, versionLabel, isPublicApi());
+ }
+
+ public String constructObjectId(NodeRef incomingNodeRef, String versionLabel, boolean dropStoreRef)
{
StringBuilder sb = new StringBuilder();
- sb.append(isPublicApi() ? incomingNodeRef.getId() : incomingNodeRef.toString());
+ sb.append(dropStoreRef ? incomingNodeRef.getId() : incomingNodeRef.toString());
if(versionLabel != null)
{
sb.append(CMISConnector.ID_SEPERATOR);
@@ -1278,29 +1293,39 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
/**
* Compiles a CMIS object if for a live node.
*/
- public String createObjectId(NodeRef currentVersionNodeRef)
+ public String createObjectId(NodeRef nodeRef)
{
- QName typeQName = nodeService.getType(currentVersionNodeRef);
+ return createObjectId(nodeRef, isPublicApi());
+ }
+
+ public String createObjectId(NodeRef nodeRef, boolean dropStoreRef)
+ {
+ QName typeQName = nodeService.getType(nodeRef);
TypeDefinitionWrapper type = getOpenCMISDictionaryService().findNodeType(typeQName);
if(type instanceof ItemTypeDefinitionWrapper)
{
- return constructObjectId(currentVersionNodeRef, null);
+ return constructObjectId(nodeRef, null);
}
if(type instanceof FolderTypeDefintionWrapper)
{
- return constructObjectId(currentVersionNodeRef, null);
+ return constructObjectId(nodeRef, null, dropStoreRef);
}
Serializable versionLabel = getNodeService()
- .getProperty(currentVersionNodeRef, ContentModel.PROP_VERSION_LABEL);
+ .getProperty(nodeRef, ContentModel.PROP_VERSION_LABEL);
if (versionLabel == null)
{
versionLabel = CMISConnector.UNVERSIONED_VERSION_LABEL;
}
- return constructObjectId(currentVersionNodeRef, (String)versionLabel);
+ return constructObjectId(nodeRef, (String)versionLabel, dropStoreRef);
+ }
+
+ private boolean isFolder(NodeRef nodeRef)
+ {
+ return getType(nodeRef) instanceof FolderTypeDefintionWrapper;
}
/**
diff --git a/source/test-java/org/alfresco/opencmis/CMISTest.java b/source/test-java/org/alfresco/opencmis/CMISTest.java
index 8a0e697566..5c980f3cef 100644
--- a/source/test-java/org/alfresco/opencmis/CMISTest.java
+++ b/source/test-java/org/alfresco/opencmis/CMISTest.java
@@ -38,12 +38,19 @@ import java.util.Map;
import java.util.Set;
import org.alfresco.cmis.CMISAccessControlService;
+import org.alfresco.cmis.CMISChangeEvent;
+import org.alfresco.cmis.CMISChangeLog;
+import org.alfresco.cmis.CMISChangeLogService;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.model.ContentModel;
import org.alfresco.opencmis.search.CMISQueryOptions;
import org.alfresco.opencmis.search.CMISQueryOptions.CMISQueryMode;
import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
import org.alfresco.repo.action.executer.AddFeaturesActionExecuter;
+import org.alfresco.repo.audit.AuditComponent;
+import org.alfresco.repo.audit.AuditServiceImpl;
+import org.alfresco.repo.audit.UserAuditFilter;
+import org.alfresco.repo.audit.model.AuditModelRegistryImpl;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.model.Repository;
@@ -134,6 +141,8 @@ public class CMISTest
private TaggingService taggingService;
private NamespaceService namespaceService;
private AuthorityService authorityService;
+ private AuditModelRegistryImpl auditSubsystem;
+ private CMISChangeLogService changeLogService;
private PermissionService permissionService;
private AlfrescoCmisServiceFactory factory;
@@ -302,6 +311,8 @@ public class CMISTest
this.cmisConnector = (CMISConnector) ctx.getBean("CMISConnector");
this.nodeDAO = (NodeDAO) ctx.getBean("nodeDAO");
this.authorityService = (AuthorityService)ctx.getBean("AuthorityService");
+ this.changeLogService = (CMISChangeLogService) ctx.getBean("CMISChangeLogService");
+ this.auditSubsystem = (AuditModelRegistryImpl) ctx.getBean("Audit");
this.permissionService = (PermissionService) ctx.getBean("permissionService");
}
@@ -2149,4 +2160,90 @@ public class CMISTest
AuthenticationUtil.popAuthentication();
}
}
+
+ /**
+ * MNT-11726: Test that {@link CMISChangeEvent} contains objectId of node in short form (without StoreRef).
+ */
+ @Test
+ public void testCMISChangeLogObjectIds() throws Exception
+ {
+ // setUp audit subsystem
+ setupAudit();
+
+ AuthenticationUtil.pushAuthentication();
+ AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
+
+ try
+ {
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
+
+ String changeToken = changeLogService.getLastChangeLogToken();
+
+ // perform CREATED, UPDATED, SECURITY, DELETED CMIS change type actions
+ String folder = GUID.generate();
+ FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folder, ContentModel.TYPE_FOLDER);
+ nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folder);
+ assertNotNull(folderInfo);
+
+ String content = GUID.generate();
+ FileInfo document = fileFolderService.create(folderInfo.getNodeRef(), content, ContentModel.TYPE_CONTENT);
+ assertNotNull(document);
+ nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, content);
+
+ permissionService.setPermission(document.getNodeRef(), "SomeAuthority", PermissionService.EXECUTE_CONTENT, true);
+
+ fileFolderService.delete(document.getNodeRef());
+ fileFolderService.delete(folderInfo.getNodeRef());
+
+ CMISChangeLog changeLogEvents = changeLogService.getChangeLogEvents(changeToken, 10);
+ // get all recent events
+ for (CMISChangeEvent event : changeLogEvents.getChangeEvents())
+ {
+ String objectId = event.getObjectId();
+ NodeRef nodeRef = event.getChangedNode();
+
+ assertFalse("CMISChangeEvent " + event.getChangeType() + " should store short form of objectId " + objectId,
+ objectId.contains(nodeRef.getStoreRef().toString()));
+ }
+
+ return null;
+ }
+ });
+
+ }
+ finally
+ {
+ auditSubsystem.destroy();
+ AuthenticationUtil.popAuthentication();
+ }
+ }
+
+ private void setupAudit()
+ {
+ UserAuditFilter userAuditFilter = new UserAuditFilter();
+ userAuditFilter.setUserFilterPattern("System;.*");
+ userAuditFilter.afterPropertiesSet();
+ AuditComponent auditComponent = (AuditComponent) ctx.getBean("auditComponent");
+ auditComponent.setUserAuditFilter(userAuditFilter);
+ AuditServiceImpl auditServiceImpl = (AuditServiceImpl) ctx.getBean("auditService");
+ auditServiceImpl.setAuditComponent(auditComponent);
+
+ RetryingTransactionCallback initAudit = new RetryingTransactionCallback()
+ {
+ public Void execute() throws Exception
+ {
+ auditSubsystem.stop();
+ auditSubsystem.setProperty("audit.enabled", "true");
+ auditSubsystem.setProperty("audit.cmischangelog.enabled", "true");
+ auditSubsystem.start();
+ return null;
+ }
+ };
+ transactionService.getRetryingTransactionHelper().doInTransaction(initAudit, false, true);
+ }
}