Files
alfresco-community-repo/src/test/java/org/alfresco/opencmis/CMISTest.java
Andrei Forascu 3583e56ba2 MNT-20139: CmisConnector returns wrong values for changeLogToken and hasMoreItems (#271)
- ensure that the returned token is always updated. This is currently not the case when there are no more items. The next token is set to null in that case, even though there might be (maxItems-1) results.
- added Junit tests
2018-11-08 11:20:54 +02:00

4034 lines
188 KiB
Java

/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.alfresco.model.ContentModel;
import org.alfresco.opencmis.dictionary.CMISDictionaryService;
import org.alfresco.opencmis.dictionary.PropertyDefinitionWrapper;
import org.alfresco.opencmis.dictionary.TypeDefinitionWrapper;
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.AuditComponentImpl;
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.dictionary.DictionaryDAO;
import org.alfresco.repo.dictionary.M2Model;
import org.alfresco.repo.domain.audit.AuditDAO;
import org.alfresco.repo.domain.node.ContentDataWithId;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.node.archive.NodeArchiveService;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationContext;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.tenant.TenantAdminService;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.repo.tenant.TenantUtil;
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.repo.version.VersionableAspectTest;
import org.alfresco.repo.workflow.WorkflowDeployer;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.action.ActionCondition;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockType;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.rule.Rule;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.cmr.rule.RuleType;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.tagging.TaggingService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.cmr.workflow.WorkflowAdminService;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.Pair;
import org.alfresco.util.testing.category.LuceneTests;
import org.alfresco.util.testing.category.RedundantTests;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.Ace;
import org.apache.chemistry.opencmis.commons.data.AllowableActions;
import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement;
import org.apache.chemistry.opencmis.commons.data.ContentStream;
import org.apache.chemistry.opencmis.commons.data.FailedToDeleteData;
import org.apache.chemistry.opencmis.commons.data.ObjectData;
import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
import org.apache.chemistry.opencmis.commons.data.ObjectList;
import org.apache.chemistry.opencmis.commons.data.ObjectParentData;
import org.apache.chemistry.opencmis.commons.data.Properties;
import org.apache.chemistry.opencmis.commons.data.PropertyData;
import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer;
import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
import org.apache.chemistry.opencmis.commons.enums.Action;
import org.apache.chemistry.opencmis.commons.enums.ChangeType;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
import org.apache.chemistry.opencmis.commons.enums.VersioningState;
import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisUpdateConflictException;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlListImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.CmisExtensionElementImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ExtensionDataImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDecimalDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl;
import org.apache.chemistry.opencmis.commons.impl.server.AbstractServiceFactory;
import org.apache.chemistry.opencmis.commons.server.CallContext;
import org.apache.chemistry.opencmis.commons.server.CmisService;
import org.apache.chemistry.opencmis.commons.server.ObjectInfo;
import org.apache.chemistry.opencmis.commons.spi.Holder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.springframework.context.ApplicationContext;
import org.springframework.extensions.webscripts.GUID;
/**
* OpenCMIS tests.
*
* @author steveglover
*
*/
@Category(LuceneTests.class)
public class CMISTest
{
private static Log logger = LogFactory.getLog(CMISTest.class);
private static final QName TEST_START_TASK = QName.createQName("http://www.alfresco.org/model/workflow/test/1.0", "startTaskVarScriptAssign");
private static final QName TEST_WORKFLOW_TASK = QName.createQName("http://www.alfresco.org/model/workflow/test/1.0", "assignVarTask");
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(new String[]{ApplicationContextHelper.CONFIG_LOCATIONS[0],"classpath:test-cmisinteger_modell-context.xml"});
private FileFolderService fileFolderService;
private TransactionService transactionService;
private NodeService nodeService;
private ContentService contentService;
private Repository repositoryHelper;
private VersionService versionService;
private LockService lockService;
private TaggingService taggingService;
private NamespaceService namespaceService;
private AuthorityService authorityService;
private AuditModelRegistryImpl auditSubsystem;
private PermissionService permissionService;
private DictionaryDAO dictionaryDAO;
private CMISDictionaryService cmisDictionaryService;
private AuditDAO auditDAO;
private ActionService actionService;
private RuleService ruleService;
private NodeArchiveService nodeArchiveService;
private DictionaryService dictionaryService;
private WorkflowService workflowService;
private WorkflowAdminService workflowAdminService;
private AuthenticationContext authenticationContext;
private TenantAdminService tenantAdminService;
private TenantService tenantService;
private SearchService searchService;
private java.util.Properties globalProperties;
private AuditComponentImpl auditComponent;
private AlfrescoCmisServiceFactory factory;
private CMISConnector cmisConnector;
private NodeDAO nodeDAO;
/**
* Test class to provide the service factory
*
* @author Derek Hulley
* @since 4.0
*/
public static class TestCmisServiceFactory extends AbstractServiceFactory
{
private static AlfrescoCmisServiceFactory serviceFactory = (AlfrescoCmisServiceFactory) ctx.getBean("CMISServiceFactory");
@Override
public void init(Map<String, String> parameters)
{
serviceFactory.init(parameters);
}
@Override
public void destroy()
{
}
@Override
public CmisService getService(CallContext context)
{
return serviceFactory.getService(context);
}
}
/**
* Test class to provide the service factory
*
* @author Derek Hulley
* @since 4.0
*/
public static class TestCmisServiceFactory11 extends AbstractServiceFactory
{
private static AlfrescoCmisServiceFactory serviceFactory = (AlfrescoCmisServiceFactory) ctx.getBean("CMISServiceFactory1.1");
@Override
public void init(Map<String, String> parameters)
{
serviceFactory.init(parameters);
}
@Override
public void destroy()
{
}
@Override
public CmisService getService(CallContext context)
{
return serviceFactory.getService(context);
}
}
public static class SimpleCallContext implements CallContext
{
private final Map<String, Object> contextMap = new HashMap<String, Object>();
private CmisVersion cmisVersion;
public SimpleCallContext(String user, String password, CmisVersion cmisVersion)
{
contextMap.put(USERNAME, user);
contextMap.put(PASSWORD, password);
this.cmisVersion = cmisVersion;
}
public String getBinding()
{
return BINDING_LOCAL;
}
public Object get(String key)
{
return contextMap.get(key);
}
public String getRepositoryId()
{
return (String) get(REPOSITORY_ID);
}
public String getUsername()
{
return (String) get(USERNAME);
}
public String getPassword()
{
return (String) get(PASSWORD);
}
public String getLocale()
{
return null;
}
public BigInteger getOffset()
{
return (BigInteger) get(OFFSET);
}
public BigInteger getLength()
{
return (BigInteger) get(LENGTH);
}
public boolean isObjectInfoRequired()
{
return false;
}
public File getTempDirectory()
{
return null;
}
public int getMemoryThreshold()
{
return 0;
}
public long getMaxContentSize()
{
return Long.MAX_VALUE;
}
@Override
public boolean encryptTempFiles()
{
return false;
}
@Override
public CmisVersion getCmisVersion()
{
return cmisVersion;
}
}
@Before
public void before()
{
this.actionService = (ActionService)ctx.getBean("actionService");
this.ruleService = (RuleService)ctx.getBean("ruleService");
this.fileFolderService = (FileFolderService)ctx.getBean("FileFolderService");
this.transactionService = (TransactionService)ctx.getBean("transactionService");
this.nodeService = (NodeService)ctx.getBean("NodeService");
this.contentService = (ContentService)ctx.getBean("ContentService");
this.versionService = (VersionService) ctx.getBean("versionService");
this.lockService = (LockService) ctx.getBean("lockService");
this.taggingService = (TaggingService) ctx.getBean("TaggingService");
this.namespaceService = (NamespaceService) ctx.getBean("namespaceService");
this.repositoryHelper = (Repository)ctx.getBean("repositoryHelper");
this.factory = (AlfrescoCmisServiceFactory)ctx.getBean("CMISServiceFactory");
this.versionService = (VersionService) ctx.getBean("versionService");
this.cmisConnector = (CMISConnector) ctx.getBean("CMISConnector");
this.nodeDAO = (NodeDAO) ctx.getBean("nodeDAO");
this.authorityService = (AuthorityService)ctx.getBean("AuthorityService");
this.auditSubsystem = (AuditModelRegistryImpl) ctx.getBean("Audit");
this.permissionService = (PermissionService) ctx.getBean("permissionService");
this.dictionaryDAO = (DictionaryDAO)ctx.getBean("dictionaryDAO");
this.cmisDictionaryService = (CMISDictionaryService)ctx.getBean("OpenCMISDictionaryService1.1");
this.auditDAO = (AuditDAO) ctx.getBean("auditDAO");
this.nodeArchiveService = (NodeArchiveService) ctx.getBean("nodeArchiveService");
this.dictionaryService = (DictionaryService) ctx.getBean("dictionaryService");
this.workflowService = (WorkflowService) ctx.getBean("WorkflowService");
this.workflowAdminService = (WorkflowAdminService) ctx.getBean("workflowAdminService");
this.authenticationContext = (AuthenticationContext) ctx.getBean("authenticationContext");
this.tenantAdminService = (TenantAdminService) ctx.getBean("tenantAdminService");
this.tenantService = (TenantService) ctx.getBean("tenantService");
this.searchService = (SearchService) ctx.getBean("SearchService");
this.auditComponent = (AuditComponentImpl) ctx.getBean("auditComponent");
this.globalProperties = (java.util.Properties) ctx.getBean("global-properties");
this.globalProperties.setProperty(VersionableAspectTest.AUTO_VERSION_PROPS_KEY, "true");
}
@After
public void after()
{
this.globalProperties.setProperty(VersionableAspectTest.AUTO_VERSION_PROPS_KEY, "false");
}
/**
* MNT-10868 CMIS: Incorrect value of Latest Major version on Versions and Properties tabs.
*/
@Test
public void testIsLatestMajorVersionMNT10868()
{
CallContext context = new SimpleCallContext("admin", "admin", CmisVersion.CMIS_1_0);
String repositoryId = null;
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
CmisService cmisService = factory.getService(context);
try
{
// get repository id
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
repositoryId = repo.getId();
final String folderName = "testfolder" + GUID.generate();
final String docName = "testdoc.txt" + GUID.generate();
final FileInfo fileInfo = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<FileInfo>()
{
@Override
public FileInfo execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
FileInfo fileInfo = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
nodeService.setProperty(fileInfo.getNodeRef(), ContentModel.PROP_NAME, docName);
nodeService.addAspect(fileInfo.getNodeRef(), ContentModel.ASPECT_VERSIONABLE, null);
return fileInfo;
}
});
ObjectData objectData = cmisService.getObjectByPath(repositoryId, "/" + folderName + "/" + docName, null, true, IncludeRelationships.NONE, null, false, true, null);
PropertyData<?> pd = getPropIsLatestMajorVersion(objectData);
if (pd != null)
{
assertTrue("The CMISDictionaryModel.PROP_IS_LATEST_MAJOR_VERSION should be true as major version was created", (Boolean) pd.getValues().get(0));
}
nodeService.setProperty(fileInfo.getNodeRef(), ContentModel.PROP_TITLE, docName);
// Create minor version
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Object>()
{
public Object execute() throws Throwable
{
// get an updating writer
ContentWriter writer = contentService.getWriter(fileInfo.getNodeRef(), ContentModel.PROP_CONTENT, true);
writer.setMimetype("text/plain");
writer.putContent("New Version");
return null;
}
});
objectData = cmisService.getObjectByPath(repositoryId, "/" + folderName + "/" + docName, null, true, IncludeRelationships.NONE, null, false, true, null);
pd = getPropIsLatestMajorVersion(objectData);
if (pd != null)
{
assertFalse("The CMISDictionaryModel.PROP_IS_LATEST_MAJOR_VERSION should be false as minor version was created", (Boolean) pd.getValues().get(0));
}
}
finally
{
cmisService.close();
}
}
private PropertyData<?> getPropIsLatestMajorVersion(ObjectData objectData)
{
List<PropertyData<?>> properties = objectData.getProperties().getPropertyList();
boolean found = false;
PropertyData<?> propIsLatestMajorVersion = null;
for (PropertyData<?> property : properties)
{
if (property.getId().equals(PropertyIds.IS_LATEST_MAJOR_VERSION))
{
found = true;
propIsLatestMajorVersion = property;
break;
}
}
//properties..contains(PropertyIds.IS_LATEST_MAJOR_VERSION);
assertTrue("The PropertyIds.IS_LATEST_MAJOR_VERSION property was not found", found);
if (found)
{
return propIsLatestMajorVersion;
}
return null;
}
/**
* Test for MNT-9203.
*/
@Test
public void testCheckIn()
{
String repositoryId = null;
ObjectData objectData = null;
Holder<String> objectId = null;
CallContext context = new SimpleCallContext("admin", "admin", CmisVersion.CMIS_1_0);
final String folderName = "testfolder." + GUID.generate();
final String docName = "testdoc.txt." + GUID.generate();
final String customModel = "cmistest.model";
final QName testCustomTypeQName = QName.createQName(customModel, "sop");
final QName authorisedByQname = QName.createQName(customModel, "authorisedBy");
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
final FileInfo fileInfo = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<FileInfo>()
{
@Override
public FileInfo execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
FileInfo fileInfo = fileFolderService.create(folderInfo.getNodeRef(), docName, testCustomTypeQName);
Map<QName, Serializable> customProperties = new HashMap<QName, Serializable>();
customProperties.put(authorisedByQname, "customPropertyString");
customProperties.put(ContentModel.PROP_NAME, docName);
nodeService.setProperties(fileInfo.getNodeRef(), customProperties);
return fileInfo;
}
});
CmisService service = factory.getService(context);
try
{
List<RepositoryInfo> repositories = service.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
repositoryId = repo.getId();
objectData = service.getObjectByPath(repositoryId, "/" + folderName + "/" + docName, null, true, IncludeRelationships.NONE, null, false, true, null);
// checkout
objectId = new Holder<String>(objectData.getId());
service.checkOut(repositoryId, objectId, null, new Holder<Boolean>(true));
}
finally
{
service.close();
}
try
{
service = factory.getService(context);
PropertyStringImpl prop = new PropertyStringImpl();
prop.setId("abc:" + authorisedByQname.toPrefixString());
prop.setValue(null);
Collection<PropertyData<?>> propsList = new ArrayList<PropertyData<?>>();
propsList.add(prop);
Properties properties = new PropertiesImpl(propsList);
// checkIn on pwc
service.checkIn(repositoryId, objectId, false, properties, null, null, null, null, null, null);
}
finally
{
service.close();
}
// check that value is null
assertTrue(nodeService.getProperty(fileInfo.getNodeRef(), authorisedByQname) == null);
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
/**
* Test for MNT-10537.
*/
@Test
public void testModelAvailability() throws Exception
{
final WorkflowDeployer testWorkflowDeployer = new WorkflowDeployer();
// setup dependencies
testWorkflowDeployer.setTransactionService(transactionService);
testWorkflowDeployer.setWorkflowService(workflowService);
testWorkflowDeployer.setWorkflowAdminService(workflowAdminService);
testWorkflowDeployer.setAuthenticationContext(authenticationContext);
testWorkflowDeployer.setDictionaryDAO(dictionaryDAO);
testWorkflowDeployer.setTenantAdminService(tenantAdminService);
testWorkflowDeployer.setTenantService(tenantService);
testWorkflowDeployer.setNodeService(nodeService);
testWorkflowDeployer.setNamespaceService(namespaceService);
testWorkflowDeployer.setSearchService(searchService);
// populate workflow parameters
java.util.Properties props = new java.util.Properties();
props.setProperty(WorkflowDeployer.ENGINE_ID, "activiti");
props.setProperty(WorkflowDeployer.LOCATION, "activiti/testCustomActiviti.bpmn20.xml");
props.setProperty(WorkflowDeployer.MIMETYPE, "text/xml");
props.setProperty(WorkflowDeployer.REDEPLOY, Boolean.FALSE.toString());
List<java.util.Properties> definitions = new ArrayList<java.util.Properties>(1);
definitions.add(props);
testWorkflowDeployer.setWorkflowDefinitions(definitions);
List<String> models = new ArrayList<String>(1);
models.add("activiti/testWorkflowModel.xml");
testWorkflowDeployer.setModels(models);
// deploy test workflow
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
txnHelper.setForceWritable(true);
txnHelper.doInTransaction(new RetryingTransactionCallback<Object>()
{
@Override
public Object execute() throws Throwable
{
return AuthenticationUtil.runAs(new RunAsWork<Object>()
{
public Object doWork()
{
testWorkflowDeployer.init();
return null;
}
}, AuthenticationUtil.getSystemUserName());
}
}, false, true);
org.alfresco.service.cmr.dictionary.TypeDefinition startTaskTypeDefinition = this.dictionaryService.getType(TEST_START_TASK);
org.alfresco.service.cmr.dictionary.TypeDefinition workflowTaskTypeDefinition = this.dictionaryService.getType(TEST_WORKFLOW_TASK);
// check that workflow types were correctly bootstrapped
assertNotNull(startTaskTypeDefinition);
assertNotNull(workflowTaskTypeDefinition);
// caches are refreshed asynchronously
Thread.sleep(5000);
// check that loaded model is available via CMIS API
CallContext context = new SimpleCallContext("admin", "admin", CmisVersion.CMIS_1_1);
CmisService service = factory.getService(context);
try
{
List<RepositoryInfo> repositories = service.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
List<TypeDefinitionContainer> container = service.getTypeDescendants(repositories.get(0).getId(), null, new BigInteger("-1"), true, null);
assertTrue("Workflow model haven't been loaded", container.toString().contains("testwf:startTaskVarScriptAssign"));
}
finally
{
service.close();
}
}
private FileInfo createContent(final String folderName, final String docName,
final boolean isRule)
{
return createContent(null, folderName, docName, isRule);
}
private FileInfo createContent(final FileInfo parentFolder, final String folderName, final String docName, final boolean isRule)
{
final FileInfo folderInfo = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<FileInfo>()
{
@Override
public FileInfo execute() throws Throwable
{
NodeRef nodeRef;
if (parentFolder != null)
{
nodeRef = parentFolder.getNodeRef();
}
else
{
nodeRef = repositoryHelper.getCompanyHome();
}
FileInfo folderInfo = fileFolderService.create(nodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
assertNotNull(folderInfo);
FileInfo fileInfo;
if (docName != null)
{
fileInfo = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
nodeService.setProperty(fileInfo.getNodeRef(), ContentModel.PROP_NAME, docName);
assertNotNull(fileInfo);
}
if (isRule)
{
Rule rule = addRule(true, folderName);
assertNotNull(rule);
// Attach the rule to the node
ruleService.saveRule(folderInfo.getNodeRef(), rule);
assertTrue(ruleService.getRules(folderInfo.getNodeRef()).size() > 0);
}
return folderInfo;
}
});
return folderInfo;
}
private Rule addRule(boolean isAppliedToChildren, String title)
{
// Rule properties
Map<String, Serializable> conditionProps = new HashMap<String, Serializable>();
conditionProps.put(ComparePropertyValueEvaluator.PARAM_VALUE, ".txt");
Map<String, Serializable> actionProps = new HashMap<String, Serializable>();
actionProps.put(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_VERSIONABLE);
List<String> ruleTypes = new ArrayList<String>(1);
ruleTypes.add(RuleType.INBOUND);
// Create the action
org.alfresco.service.cmr.action.Action action = actionService.createAction(title);
action.setParameterValues(conditionProps);
ActionCondition actionCondition = actionService.createActionCondition(ComparePropertyValueEvaluator.NAME);
actionCondition.setParameterValues(conditionProps);
action.addActionCondition(actionCondition);
// Create the rule
Rule rule = new Rule();
rule.setRuleTypes(ruleTypes);
rule.setTitle(title);
rule.setDescription("description");
rule.applyToChildren(isAppliedToChildren);
rule.setAction(action);
return rule;
}
private <T extends Object> T withCmisService(CmisServiceCallback<T> callback)
{
return withCmisService(callback, CmisVersion.CMIS_1_0);
}
private <T extends Object> T withCmisService(CmisServiceCallback<T> callback, CmisVersion cmisVersion)
{
CmisService cmisService = null;
try
{
CallContext context = new SimpleCallContext("admin", "admin", cmisVersion);
cmisService = factory.getService(context);
T ret = callback.execute(cmisService);
return ret;
}
finally
{
if(cmisService != null)
{
cmisService.close();
}
}
}
private static interface CmisServiceCallback<T>
{
T execute(CmisService cmisService);
}
/**
* ALF-18006 Test content mimetype auto-detection into CmisStreamInterceptor when "Content-Type" is not defined.
*/
@Test
public void testContentMimeTypeDetection()
{
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
FileFolderService ffs = serviceRegistry.getFileFolderService();
AuthenticationComponent authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
final String isoEncoding = "ISO-8859-1";
final String utfEncoding = "UTF-8";
// get repository id
List<RepositoryInfo> repositories = withCmisService(new CmisServiceCallback<List<RepositoryInfo>>()
{
@Override
public List<RepositoryInfo> execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
return repositories;
}
});
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
final String repositoryId = repo.getId();
// create simple text plain content
final PropertiesImpl properties = new PropertiesImpl();
String objectTypeId = "cmis:document";
properties.addProperty(new PropertyIdImpl(PropertyIds.OBJECT_TYPE_ID, objectTypeId));
String fileName = "textFile" + GUID.generate();
properties.addProperty(new PropertyStringImpl(PropertyIds.NAME, fileName));
final ContentStreamImpl contentStream = new ContentStreamImpl(fileName, MimetypeMap.MIMETYPE_TEXT_PLAIN, "Simple text plain document");
String objectId = withCmisService(new CmisServiceCallback<String>()
{
@Override
public String execute(CmisService cmisService)
{
String objectId = cmisService.create(repositoryId, properties, repositoryHelper.getCompanyHome().getId(), contentStream, VersioningState.MAJOR, null, null);
return objectId;
}
});
final Holder<String> objectIdHolder = new Holder<String>(objectId);
final String path = "/" + fileName;
// create content stream with undefined mimetype and file name
{
final ContentStreamImpl contentStreamHTML = new ContentStreamImpl(null, null, "<html><head><title> Hello </title></head><body><p> Test html</p></body></html></body></html>");
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
cmisService.setContentStream(repositoryId, objectIdHolder, true, null, contentStreamHTML, null);
return null;
}
});
// check mimetype
ObjectData objectData = withCmisService(new CmisServiceCallback<ObjectData>()
{
@Override
public ObjectData execute(CmisService cmisService)
{
return cmisService.getObjectByPath(repositoryId, path, null, false, IncludeRelationships.NONE, null, false, false, null);
}
});
final String objectId1 = objectData.getId();
String contentType = withCmisService(new CmisServiceCallback<String>()
{
@Override
public String execute(CmisService cmisService)
{
String contentType = cmisService.getObjectInfo(repositoryId, objectId1).getContentType();
return contentType;
}
});
assertEquals("Mimetype is not defined correctly.", MimetypeMap.MIMETYPE_HTML, contentType);
// check that the encoding is detected correctly
checkEncoding(ffs, authenticationComponent, objectData, utfEncoding);
}
// create content stream with mimetype and encoding as UTF-8
{
String mimeType = MimetypeMap.MIMETYPE_TEXT_PLAIN + "; charset="+isoEncoding;
// NOTE that we intentionally specify the wrong charset here.
// Alfresco will detect the encoding (as UTF-8 - given by the ContentStreamImpl constructor)
final ContentStreamImpl contentStreamHTML = new ContentStreamImpl(null, mimeType, "<html><head><title> Hello </title></head><body><p> Test html</p></body></html></body></html>");
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
Holder<String> latestObjectIdHolder = getHolderOfObjectOfLatestVersion(cmisService, repositoryId, objectIdHolder);
cmisService.setContentStream(repositoryId, latestObjectIdHolder, true, null, contentStreamHTML, null);
return null;
}
});
// check mimetype
final ObjectData objectData = withCmisService(new CmisServiceCallback<ObjectData>()
{
@Override
public ObjectData execute(CmisService cmisService)
{
ObjectData objectData = cmisService.getObjectByPath(repositoryId, path, null, false, IncludeRelationships.NONE, null, false, false, null);
return objectData;
}
});
String contentType = withCmisService(new CmisServiceCallback<String>()
{
@Override
public String execute(CmisService cmisService)
{
String contentType = cmisService.getObjectInfo(repositoryId, objectData.getId()).getContentType();
return contentType;
}
});
assertEquals("Mimetype is not defined correctly.", MimetypeMap.MIMETYPE_TEXT_PLAIN, contentType);
// check that the encoding is detected correctly
checkEncoding(ffs, authenticationComponent, objectData, utfEncoding);
}
// create content stream with mimetype and encoding as ISO-8859-1
{
String mimeType = MimetypeMap.MIMETYPE_TEXT_PLAIN + "; charset=" + utfEncoding;
// NOTE that we intentionally specify the wrong charset here.
// Alfresco will detect the encoding (as ISO-8859-1 - given by the ContentStreamImpl with streams)
String content = "<html><head><title>aegif Mind Share Leader Generating New Paradigms by aegif corporation</title></head><body><p> Test html</p></body></html></body></html>";
byte[] buf = null;
try
{
buf = content.getBytes(isoEncoding); // set the encoding here for the content stream
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
ByteArrayInputStream input = new ByteArrayInputStream(buf);
final ContentStream contentStreamHTML = new ContentStreamImpl(null, BigInteger.valueOf(buf.length), mimeType, input);
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
Holder<String> latestObjectIdHolder = getHolderOfObjectOfLatestVersion(cmisService, repositoryId,
objectIdHolder);
cmisService.setContentStream(repositoryId, latestObjectIdHolder, true, null, contentStreamHTML, null);
return null;
}
});
// check mimetype
final ObjectData objectData = withCmisService(new CmisServiceCallback<ObjectData>()
{
@Override
public ObjectData execute(CmisService cmisService)
{
ObjectData objectData = cmisService.getObjectByPath(repositoryId, path, null, false,
IncludeRelationships.NONE, null, false, false, null);
return objectData;
}
});
String contentType = withCmisService(new CmisServiceCallback<String>()
{
@Override
public String execute(CmisService cmisService)
{
String contentType = cmisService.getObjectInfo(repositoryId, objectData.getId()).getContentType();
return contentType;
}
});
assertEquals("Mimetype is not defined correctly.", MimetypeMap.MIMETYPE_TEXT_PLAIN, contentType);
// check that the encoding is detected correctly
checkEncoding(ffs, authenticationComponent, objectData, isoEncoding);
}
// checkout/checkin object with mimetype and encoding
{
ObjectData objectDa = withCmisService(new CmisServiceCallback<ObjectData>()
{
@Override
public ObjectData execute(CmisService cmisService)
{
return cmisService.getObjectByPath(repositoryId, path, null, false, IncludeRelationships.NONE, null, false, false, null);
}
});
objectIdHolder.setValue(objectDa.getId());
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
cmisService.checkOut(repositoryId, objectIdHolder, null, new Holder<Boolean>());
return null;
}
});
String mimeType = MimetypeMap.MIMETYPE_HTML + "; charset=UTF-8";
final ContentStreamImpl contentStreamHTML = new ContentStreamImpl(null, mimeType, "<html><head><title> Hello </title></head><body><p> Test html</p></body></html></body></html>");
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
cmisService.checkIn(repositoryId, objectIdHolder, false, null, contentStreamHTML, "checkin", null, null, null, null);
return null;
}
});
// check mimetype
final ObjectData objectData = withCmisService(new CmisServiceCallback<ObjectData>()
{
@Override
public ObjectData execute(CmisService cmisService)
{
ObjectData objectData = cmisService.getObjectByPath(repositoryId, path, null, false, IncludeRelationships.NONE, null, false, false, null);
return objectData;
}
});
String contentType = withCmisService(new CmisServiceCallback<String>()
{
@Override
public String execute(CmisService cmisService)
{
String contentType = cmisService.getObjectInfo(repositoryId, objectData.getId()).getContentType();
return contentType;
}
});
assertEquals("Mimetype is not defined correctly.", MimetypeMap.MIMETYPE_HTML, contentType);
checkEncoding(ffs, authenticationComponent, objectData, utfEncoding);
}
}
protected void checkEncoding(FileFolderService ffs, AuthenticationComponent authenticationComponent,
final ObjectData objectData, String expectedEncoding)
{
// Authenticate as system to check the properties in alfresco
authenticationComponent.setSystemUserAsCurrentUser();
try
{
NodeRef doc1NodeRef = cmisIdToNodeRef(objectData.getId());
doc1NodeRef.getId();
FileInfo fileInfo = ffs.getFileInfo(doc1NodeRef);
Map<QName, Serializable> properties2 = fileInfo.getProperties();
ContentDataWithId contentData = (ContentDataWithId) properties2
.get(QName.createQName("{http://www.alfresco.org/model/content/1.0}content"));
String encoding = contentData.getEncoding();
assertEquals(expectedEncoding, encoding);
}
finally
{
authenticationComponent.clearCurrentSecurityContext();
}
}
/**
* Turns a CMIS id into a node ref
* @param nodeId
* @return
*/
private NodeRef cmisIdToNodeRef(String nodeId)
{
int idx = nodeId.indexOf(";");
if(idx != -1)
{
nodeId = nodeId.substring(0, idx);
}
NodeRef nodeRef = new NodeRef(nodeId);
return nodeRef;
}
private Holder<String> getHolderOfObjectOfLatestVersion(CmisService cmisService, String repositoryId, Holder<String> currentHolder)
{
ObjectData oData = cmisService.getObjectOfLatestVersion(repositoryId, currentHolder.getValue(), null, Boolean.FALSE, null, null, null, null, null, null, null);
return new Holder<String>(oData.getId());
}
/**
* ALF-20389 Test Alfresco cmis stream interceptor that checks content stream for mimetype. Only ContentStreamImpl extensions should take palace.
*/
@Test
public void testGetRepositoryInfos()
{
boolean cmisEx = false;
List<RepositoryInfo> infoDataList = null;
try
{
infoDataList = withCmisService(new CmisServiceCallback<List<RepositoryInfo>>()
{
@Override
public List<RepositoryInfo> execute(CmisService cmisService)
{
ExtensionDataImpl result = new ExtensionDataImpl();
List<CmisExtensionElement> extensions = new ArrayList<CmisExtensionElement>();
result.setExtensions(extensions);
return cmisService.getRepositoryInfos(result);
}
});
}
catch (CmisRuntimeException e)
{
cmisEx = true;
}
assertNotNull(cmisEx ? "CmisRuntimeException was thrown. Please, take a look on ALF-20389" : "No CMIS repository information was retrieved", infoDataList);
}
private static class TestContext
{
private String repositoryId = null;
@SuppressWarnings("unused")
private ObjectData objectData = null;
private Holder<String> objectId = null;
public TestContext()
{
super();
}
public String getRepositoryId()
{
return repositoryId;
}
public void setRepositoryId(String repositoryId)
{
this.repositoryId = repositoryId;
}
public void setObjectData(ObjectData objectData)
{
this.objectData = objectData;
}
public Holder<String> getObjectId()
{
return objectId;
}
public void setObjectId(Holder<String> objectId)
{
this.objectId = objectId;
}
}
/**
* Test for ALF-16310.
*
* Check that, for AtomPub binding, cancel checkout on the originating checked out document i.e. not the working
* copy throws an exception and does not delete the document.
*/
@SuppressWarnings("unchecked")
@Test
public void testCancelCheckout()
{
final TestContext testContext = new TestContext();
final String folderName = "testfolder." + GUID.generate();
final String docName = "testdoc.txt." + GUID.generate();
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
final FileInfo folderInfo = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<FileInfo>()
{
@Override
public FileInfo execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
FileInfo fileInfo = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
nodeService.setProperty(fileInfo.getNodeRef(), ContentModel.PROP_NAME, docName);
return folderInfo;
}
});
final ObjectData objectData = withCmisService(new CmisServiceCallback<ObjectData>()
{
@Override
public ObjectData execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
testContext.setRepositoryId(repositoryId);
ObjectData objectData = cmisService.getObjectByPath(repositoryId, "/" + folderName + "/" + docName, null, true,
IncludeRelationships.NONE, null, false, true, null);
testContext.setObjectData(objectData);
// checkout
Holder<String> objectId = new Holder<String>(objectData.getId());
testContext.setObjectId(objectId);
cmisService.checkOut(repositoryId, objectId, null, new Holder<Boolean>(true));
return objectData;
}
});
// AtomPub cancel checkout
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
try
{
// check allowable actions
ObjectData originalDoc = cmisService.getObject(testContext.getRepositoryId(), objectData.getId(), null, true, IncludeRelationships.NONE, null, false, true, null);
AllowableActions allowableActions = originalDoc.getAllowableActions();
assertNotNull(allowableActions);
assertFalse(allowableActions.getAllowableActions().contains(Action.CAN_DELETE_OBJECT));
// try to cancel the checkout
cmisService.deleteObjectOrCancelCheckOut(testContext.getRepositoryId(), objectData.getId(), Boolean.TRUE, null);
fail();
}
catch(CmisConstraintException e)
{
// expected
}
return null;
}
});
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
// cancel checkout on pwc
cmisService.deleteObjectOrCancelCheckOut(testContext.getRepositoryId(), testContext.getObjectId().getValue(), Boolean.TRUE, null);
return null;
}
});
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
// get original document
ObjectData originalDoc = cmisService.getObject(testContext.getRepositoryId(), objectData.getId(), null, true, IncludeRelationships.NONE, null, false, true, null);
Map<String, PropertyData<?>> properties = originalDoc.getProperties().getProperties();
PropertyData<Boolean> isVersionSeriesCheckedOutProp = (PropertyData<Boolean>)properties.get(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT);
assertNotNull(isVersionSeriesCheckedOutProp);
Boolean isVersionSeriesCheckedOut = isVersionSeriesCheckedOutProp.getFirstValue();
assertNotNull(isVersionSeriesCheckedOut);
assertEquals(Boolean.FALSE, isVersionSeriesCheckedOut);
return null;
}
});
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
// delete original document
cmisService.deleteObject(testContext.getRepositoryId(), objectData.getId(), true, null);
return null;
}
});
List<FileInfo> children = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<List<FileInfo>>()
{
@Override
public List<FileInfo> execute() throws Throwable
{
List<FileInfo> children = fileFolderService.list(folderInfo.getNodeRef());
return children;
}
});
assertEquals(0, children.size());
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
/**
* Test for MNT-13366.
*/
@Test
public void testDeleteTree()
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
FileInfo parentFolder = null;
FileInfo childFolder1 = null;
try
{
// Create a parent folder: parentFolder:
String parentFolderName = "parentFolder" + GUID.generate();
parentFolder = createContent(parentFolderName, null, false);
final NodeRef parentFolderNodeRef = parentFolder.getNodeRef();
final String parentFolderID = parentFolderNodeRef.getId();
// Create a child folder: parentFolder -> childFolder1:
String childFolder1Name = "childFolder1" + GUID.generate();
childFolder1 = createContent(parentFolder, childFolder1Name, null, false);
final NodeRef childFolder1NodeRef = childFolder1.getNodeRef();
// Create a child folder for previous child folder, which will contain a file:
// parentFolder -> childFolder1 -> childFolder2 -> testdoc.txt
String childFolder2Name = "childFolder2" + GUID.generate();
String docName = "testdoc.txt" + GUID.generate();
final NodeRef childFolder2NodeRef = createContent(childFolder1, childFolder2Name, docName, false).getNodeRef();
// Store a reference to the file "testdoc.txt" contained by childFolder2:
List<FileInfo> childFolder2FileList = fileFolderService.list(childFolder2NodeRef);
final NodeRef childFolder2FileNodeRef = childFolder2FileList.get(0).getNodeRef();
List<RepositoryInfo> repositories = withCmisService(new CmisServiceCallback<List<RepositoryInfo>>()
{
@Override
public List<RepositoryInfo> execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
return repositories;
}
});
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
final String repositoryId = repo.getId();
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
// CMIS delete tree:
FailedToDeleteData failedItems = cmisService.deleteTree(repositoryId, parentFolderID, Boolean.TRUE,
UnfileObject.DELETE, Boolean.TRUE, null);
assertEquals(failedItems.getIds().size(), 0);
// Reference to the archive root node (the trash-can):
NodeRef archiveRootNode = nodeArchiveService.getStoreArchiveNode(repositoryHelper.getCompanyHome().getStoreRef());
// Get the archived ("canned") version of folders and file and check that hirarchy is correct:
// ArchiveRoot -> archivedParentFolder -> archivedChildFolder1 -> archivedChildFolder2 -> archivedChildFolder2File.
// Check parentFolder:
NodeRef archivedParentFolderNodeRef = nodeArchiveService.getArchivedNode(parentFolderNodeRef);
assertTrue(nodeService.getPrimaryParent(archivedParentFolderNodeRef).getParentRef().equals(archiveRootNode));
// Check childFolder1:
NodeRef archivedChildFolder1NodeRef = nodeArchiveService.getArchivedNode(childFolder1NodeRef);
assertTrue(nodeService.getPrimaryParent(archivedChildFolder1NodeRef).getParentRef().equals(archivedParentFolderNodeRef));
assertFalse(nodeService.getPrimaryParent(archivedChildFolder1NodeRef).getParentRef().equals(archiveRootNode));
// Check childFolder2:
NodeRef archivedChildFolder2NodeRef = nodeArchiveService.getArchivedNode(childFolder2NodeRef);
assertTrue(nodeService.getPrimaryParent(archivedChildFolder2NodeRef).getParentRef().equals(archivedChildFolder1NodeRef));
assertFalse(nodeService.getPrimaryParent(archivedChildFolder2NodeRef).getParentRef().equals(archiveRootNode));
// Check childFolder2's file ("testdoc.txt"):
NodeRef archivedChildFolder2FileNodeRef = nodeArchiveService.getArchivedNode(childFolder2FileNodeRef);
assertTrue(nodeService.getPrimaryParent(archivedChildFolder2FileNodeRef).getParentRef().equals(archivedChildFolder2NodeRef));
assertFalse(nodeService.getPrimaryParent(archivedChildFolder2FileNodeRef).getParentRef().equals(archiveRootNode));
return null;
};
});
}
finally
{
if (parentFolder != null && fileFolderService.exists(parentFolder.getNodeRef()))
{
fileFolderService.delete(parentFolder.getNodeRef());
}
AuthenticationUtil.popAuthentication();
}
}
/**
* Test for ALF-18151.
*/
@Test
public void testDeleteFolder()
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
final Map<FileInfo, Boolean> testFolderMap = new HashMap<FileInfo, Boolean>(4);
try
{
// create folder with file
String folderName = "testfolder" + GUID.generate();
String docName = "testdoc.txt" + GUID.generate();
FileInfo folder = createContent(folderName, docName, false);
testFolderMap.put(folder, Boolean.FALSE);
// create empty folder
String folderNameEmpty = "testfolder_empty1" + GUID.generate();
FileInfo folderEmpty = createContent(folderNameEmpty, null, false);
testFolderMap.put(folderEmpty, Boolean.TRUE);
// create folder with file
String folderNameRule = "testfolde_rule" + GUID.generate();
String docNameRule = "testdoc_rule.txt" + GUID.generate();
FileInfo folderWithRule = createContent(folderNameRule, docNameRule, true);
testFolderMap.put(folderWithRule, Boolean.FALSE);
// create empty folder
String folderNameEmptyRule = "testfolde_empty_rule1" + GUID.generate();
FileInfo folderEmptyWithRule = createContent(folderNameEmptyRule, null, true);
testFolderMap.put(folderEmptyWithRule, Boolean.TRUE);
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
for (Map.Entry<FileInfo, Boolean> entry : testFolderMap.entrySet())
{
ObjectData objectData = cmisService.getObjectByPath(repositoryId, "/" + entry.getKey().getName(), null, true, IncludeRelationships.NONE, null, false, true, null);
Holder<String> objectId = new Holder<String>(objectData.getId());
try
{
// delete folder
cmisService.deleteObjectOrCancelCheckOut(repositoryId, objectId.getValue(), Boolean.TRUE, null);
}
catch (CmisConstraintException ex)
{
assertTrue(!entry.getValue());
continue;
}
assertTrue(entry.getValue());
}
return null;
}
});
}
finally
{
for (Map.Entry<FileInfo, Boolean> entry : testFolderMap.entrySet())
{
if (fileFolderService.exists(entry.getKey().getNodeRef()))
{
fileFolderService.delete(entry.getKey().getNodeRef());
}
}
AuthenticationUtil.popAuthentication();
}
}
/**
* Test
* <ul>
* <li>MNT-8825: READ_ONLYLOCK prevent getAllVersions via new CMIS enpoint.</li>
* <li>ACE-762: BM-0012: NodeLockedException not handled by CMIS</li>
* </ul>
*/
@Test
public void testOperationsOnReadOnlyLockedNode()
{
final String folderName = "testfolder." + GUID.generate();
final String docName = "testdoc.txt." + GUID.generate();
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
try
{
final FileInfo fileInfo = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<FileInfo>()
{
@Override
public FileInfo execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
FileInfo fileInfo = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
nodeService.setProperty(fileInfo.getNodeRef(), ContentModel.PROP_NAME, docName);
versionService.createVersion(fileInfo.getNodeRef(), new HashMap<String, Serializable>());
lockService.lock(fileInfo.getNodeRef(), LockType.READ_ONLY_LOCK, 0, true);
return fileInfo;
}
});
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
ObjectData objectData = cmisService.getObjectByPath(repositoryId, "/" + folderName + "/" + docName, null, true,
IncludeRelationships.NONE, null, false, true, null);
// Expect no failure
cmisService.getAllVersions(repositoryId, objectData.getId(), fileInfo.getNodeRef().getId(), null, true, null);
return null;
}
});
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
ObjectData objectData = cmisService.getObjectByPath(
repositoryId, "/" + folderName + "/" + docName, null, true,
IncludeRelationships.NONE, null, false, true, null);
String objectId = objectData.getId();
// Expect failure as the node is locked
try
{
cmisService.deleteObject(repositoryId, objectId, true, null);
fail("Locked node should not be deletable.");
}
catch (CmisUpdateConflictException e)
{
// Expected
}
return null;
}
});
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
/**
* ALF-18455
*/
@Test
public void testOrderByCreationAndModificationDate()
{
final List<FileInfo> nodes = new ArrayList<FileInfo>(10);
final List<FileInfo> expectedChildrenByCreationDate = new ArrayList<FileInfo>(10);
final List<FileInfo> expectedChildrenByModificationDate = new ArrayList<FileInfo>(10);
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
String folderName = GUID.generate();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
assertNotNull(folderInfo);
nodes.add(folderInfo);
for(int i = 0; i < 5; i++)
{
String docName = GUID.generate();
FileInfo fileInfo = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
assertNotNull(fileInfo);
nodeService.setProperty(fileInfo.getNodeRef(), ContentModel.PROP_NAME, docName);
expectedChildrenByCreationDate.add(0, fileInfo);
nodes.add(fileInfo);
// make sure there is some difference in creation times
Thread.sleep(400);
}
// make modifications
for(int i = 5; i > 0; i--)
{
FileInfo fileInfo = nodes.get(i);
assertNotNull(fileInfo);
nodeService.setProperty(fileInfo.getNodeRef(), ContentModel.PROP_DESCRIPTION, GUID.generate());
// "refresh" fileInfo
fileInfo = fileFolderService.getFileInfo(fileInfo.getNodeRef());
assertNotNull(fileInfo);
expectedChildrenByModificationDate.add(0, fileInfo);
// make sure there is some difference in modification times
Thread.sleep(400);
}
return null;
}
});
}
finally
{
AuthenticationUtil.popAuthentication();
}
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
// get repository id
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
String folderId = nodes.get(0).getNodeRef().getId();
String orderBy = PropertyIds.CREATION_DATE + " DESC";
ObjectInFolderList children = cmisService.getChildren(repositoryId, folderId, null, orderBy, false, IncludeRelationships.NONE,
null, false, BigInteger.valueOf(Integer.MAX_VALUE), BigInteger.valueOf(0), null);
int i = 0;
for(ObjectInFolderData child : children.getObjects())
{
Map<String, PropertyData<?>> properties = child.getObject().getProperties().getProperties();
PropertyData<?> pObjectId = properties.get(PropertyIds.VERSION_SERIES_ID);
String actualObjectId = (String)pObjectId.getFirstValue();
PropertyData<?> pCreationDate = properties.get(PropertyIds.CREATION_DATE);
GregorianCalendar actualCreationDate = (GregorianCalendar)pCreationDate.getFirstValue();
FileInfo expectedChild = expectedChildrenByCreationDate.get(i++);
assertEquals(expectedChild.getNodeRef().toString(), actualObjectId);
assertEquals(expectedChild.getCreatedDate().getTime(), actualCreationDate.getTimeInMillis());
}
orderBy = PropertyIds.LAST_MODIFICATION_DATE + " DESC";
children = cmisService.getChildren(repositoryId, folderId, null, orderBy, false, IncludeRelationships.NONE,
null, false, BigInteger.valueOf(Integer.MAX_VALUE), BigInteger.valueOf(0), null);
i = 0;
for(ObjectInFolderData child : children.getObjects())
{
Map<String, PropertyData<?>> properties = child.getObject().getProperties().getProperties();
PropertyData<?> pObjectId = properties.get(PropertyIds.VERSION_SERIES_ID);
String actualObjectId = (String)pObjectId.getFirstValue();
PropertyData<?> pModificationDate = properties.get(PropertyIds.LAST_MODIFICATION_DATE);
GregorianCalendar actualModificationDate = (GregorianCalendar)pModificationDate.getFirstValue();
FileInfo expectedChild = expectedChildrenByModificationDate.get(i++);
assertEquals(expectedChild.getNodeRef().toString(), actualObjectId);
assertEquals(expectedChild.getModifiedDate().getTime(), actualModificationDate.getTimeInMillis());
}
return null;
}
});
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test
public void testSecondaryTypes()
{
final String aspectName = "P:cm:indexControl";
// get repository id
final String repositoryId = withCmisService(new CmisServiceCallback<String>()
{
@Override
public String execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
final String repositoryId = repo.getId();
return repositoryId;
}
}, CmisVersion.CMIS_1_1);
final String objectId = withCmisService(new CmisServiceCallback<String>()
{
@Override
public String execute(CmisService cmisService)
{
final PropertiesImpl properties = new PropertiesImpl();
String objectTypeId = "cmis:document";
properties.addProperty(new PropertyIdImpl(PropertyIds.OBJECT_TYPE_ID, objectTypeId));
String fileName = "textFile" + GUID.generate();
properties.addProperty(new PropertyStringImpl(PropertyIds.NAME, fileName));
final ContentStreamImpl contentStream = new ContentStreamImpl(fileName, MimetypeMap.MIMETYPE_TEXT_PLAIN, "Simple text plain document");
String objectId = cmisService.create(repositoryId, properties, repositoryHelper.getCompanyHome().getId(), contentStream, VersioningState.MAJOR, null, null);
return objectId;
}
}, CmisVersion.CMIS_1_1);
final Holder<String> objectIdHolder = new Holder<String>(objectId);
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
final PropertiesImpl properties = new PropertiesImpl();
properties.addProperty(new PropertyStringImpl(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, Arrays.asList(aspectName)));
cmisService.updateProperties(repositoryId, objectIdHolder, null, properties, null);
return null;
}
}, CmisVersion.CMIS_1_1);
final Properties currentProperties = withCmisService(new CmisServiceCallback<Properties>()
{
@Override
public Properties execute(CmisService cmisService)
{
Properties properties = cmisService.getProperties(repositoryId, objectIdHolder.getValue(), null, null);
return properties;
}
}, CmisVersion.CMIS_1_1);
List<String> secondaryTypeIds = (List<String>) currentProperties.getProperties().get(PropertyIds.SECONDARY_OBJECT_TYPE_IDS).getValues();
assertTrue(secondaryTypeIds.contains(aspectName));
// We don't actually want to add these! (REPO-2926)
final Set<String> sysAspectsToAdd = new HashSet<>(Arrays.asList(
"P:sys:undeletable",
"P:sys:hidden"));
// Pre-condition of further test is that these aspects are not present
assertEquals(0, secondaryTypeIds.stream().filter(sysAspectsToAdd::contains).count());
// We also want to check that existing sys aspects aren't accidentally removed
assertTrue(secondaryTypeIds.contains("P:sys:localized"));
// Check we can remove an aspect - through its absence
secondaryTypeIds.remove(aspectName);
// Check that attempts to update/add sys:* aspects are ignored
secondaryTypeIds.addAll(sysAspectsToAdd);
final PropertiesImpl newProperties = new PropertiesImpl();
newProperties.addProperty(new PropertyStringImpl(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryTypeIds));
final String updatedName = "My_new_name_"+UUID.randomUUID().toString();
newProperties.replaceProperty(new PropertyStringImpl(PropertyIds.NAME, updatedName));
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
Holder<String> latestObjectIdHolder = getHolderOfObjectOfLatestVersion(cmisService, repositoryId, objectIdHolder);
// This will result in aspectName being removed
// but that shouldn't mean that, for example, a cmis:name prop update gets ignored (MNT-18340)
cmisService.updateProperties(repositoryId, latestObjectIdHolder, null, newProperties, null);
return null;
}
}, CmisVersion.CMIS_1_1);
Properties currentProperties1 = withCmisService(new CmisServiceCallback<Properties>()
{
@Override
public Properties execute(CmisService cmisService)
{
Holder<String> latestObjectIdHolder = getHolderOfObjectOfLatestVersion(cmisService, repositoryId, objectIdHolder);
Properties properties = cmisService.getProperties(repositoryId, latestObjectIdHolder.getValue(), null, null);
return properties;
}
}, CmisVersion.CMIS_1_1);
secondaryTypeIds = (List<String>) currentProperties1.getProperties().get(PropertyIds.SECONDARY_OBJECT_TYPE_IDS).getValues();
assertFalse(secondaryTypeIds.contains(aspectName));
assertEquals(updatedName, currentProperties1.getProperties().get(PropertyIds.NAME).getFirstValue());
// sys aspects must not be added through CMIS (REPO-2926)
assertEquals(0, secondaryTypeIds.stream().filter(sysAspectsToAdd::contains).count());
// Check pre-existing sys aspects aren't accidentally removed
assertTrue(secondaryTypeIds.contains("P:sys:localized"));
}
/**
* Test for MNT-9089
*/
@Test
public void testIntegerBoudaries() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
final FileInfo fileInfo = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<FileInfo>()
{
@Override
public FileInfo execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
QName testIntTypeQName = QName.createQName("http://testCMISIntegersModel/1.0/", "testintegerstype");
String folderName = GUID.generate();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
assertNotNull(folderInfo);
String docName = GUID.generate();
FileInfo fileInfo = fileFolderService.create(folderInfo.getNodeRef(), docName, testIntTypeQName);
assertNotNull(fileInfo);
nodeService.setProperty(fileInfo.getNodeRef(), ContentModel.PROP_NAME, docName);
return fileInfo;
}
});
// get repository id
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
String objectIdStr = fileInfo.getNodeRef().toString();
TypeDefinition typeDef = cmisService.getTypeDefinition(repositoryId, "D:tcim:testintegerstype", null);
PropertyIntegerDefinitionImpl intNoBoundsTypeDef =
(PropertyIntegerDefinitionImpl)typeDef.getPropertyDefinitions().get("tcim:int");
PropertyIntegerDefinitionImpl longNoBoundsTypeDef =
(PropertyIntegerDefinitionImpl)typeDef.getPropertyDefinitions().get("tcim:long");
PropertyIntegerDefinitionImpl intWithBoundsTypeDef =
(PropertyIntegerDefinitionImpl)typeDef.getPropertyDefinitions().get("tcim:intwithbounds");
PropertyIntegerDefinitionImpl longWithBoundsTypeDef =
(PropertyIntegerDefinitionImpl)typeDef.getPropertyDefinitions().get("tcim:longwithbounds");
BigInteger minInteger = BigInteger.valueOf(Integer.MIN_VALUE);
BigInteger maxInteger = BigInteger.valueOf(Integer.MAX_VALUE);
BigInteger minLong = BigInteger.valueOf(Long.MIN_VALUE);
BigInteger maxLong = BigInteger.valueOf(Long.MAX_VALUE);
// test for default boundaries
assertTrue(intNoBoundsTypeDef.getMinValue().equals(minInteger));
assertTrue(intNoBoundsTypeDef.getMaxValue().equals(maxInteger));
assertTrue(longNoBoundsTypeDef.getMinValue().equals(minLong));
assertTrue(longNoBoundsTypeDef.getMaxValue().equals(maxLong));
// test for pre-defined boundaries
assertTrue(intWithBoundsTypeDef.getMinValue().equals(BigInteger.valueOf(-10L)));
assertTrue(intWithBoundsTypeDef.getMaxValue().equals(BigInteger.valueOf(10L)));
assertTrue(longWithBoundsTypeDef.getMinValue().equals(BigInteger.valueOf(-10L)));
assertTrue(longWithBoundsTypeDef.getMaxValue().equals(BigInteger.valueOf(10L)));
try // try to overfloat long without boundaries
{
BigInteger aValue = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.valueOf(1L));
setProperiesToObject(cmisService, repositoryId, objectIdStr, "tcim:long", aValue);
fail();
}
catch(Exception e)
{
assertTrue(e instanceof CmisConstraintException);
}
try // try to overfloat int without boundaries
{
BigInteger aValue = BigInteger.valueOf(Integer.MAX_VALUE).add(BigInteger.valueOf(1L));
setProperiesToObject(cmisService, repositoryId, objectIdStr, "tcim:int", aValue);
fail();
}
catch(Exception e)
{
assertTrue(e instanceof CmisConstraintException);
}
try // try to overfloat int with boundaries
{
BigInteger aValue = BigInteger.valueOf( 11l );
setProperiesToObject(cmisService, repositoryId, objectIdStr, "tcim:intwithbounds", aValue);
fail();
}
catch(Exception e)
{
assertTrue(e instanceof CmisConstraintException);
}
try // try to overfloat long with boundaries
{
BigInteger aValue = BigInteger.valueOf( 11l );
setProperiesToObject(cmisService, repositoryId, objectIdStr, "tcim:longwithbounds", aValue);
fail();
}
catch(Exception e)
{
assertTrue(e instanceof CmisConstraintException);
}
return null;
}
}, CmisVersion.CMIS_1_0);
}
catch(Exception e)
{
fail(e.getMessage());
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
private void setProperiesToObject(CmisService cmisService, String repositoryId, String objectIdStr, String propertyStr, BigInteger bigIntValue) throws CmisConstraintException{
Properties properties = cmisService.getProperties(repositoryId, objectIdStr, null, null);
PropertyIntegerImpl pd = (PropertyIntegerImpl)properties.getProperties().get(propertyStr);
pd.setValue(bigIntValue);
Collection<PropertyData<?>> propsList = new ArrayList<PropertyData<?>>();
propsList.add(pd);
Properties newProps = new PropertiesImpl(propsList);
cmisService.updateProperties(repositoryId, new Holder<String>(objectIdStr), null, newProps, null);
}
@Test
public void testMNT9090() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
final FileInfo fileInfo = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<FileInfo>()
{
@Override
public FileInfo execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
String folderName = GUID.generate();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
assertNotNull(folderInfo);
String docName = GUID.generate();
FileInfo fileInfo = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
assertNotNull(fileInfo);
nodeService.setProperty(fileInfo.getNodeRef(), ContentModel.PROP_NAME, docName);
QName ASPECT_AUDIO = QName.createQName(NamespaceService.AUDIO_MODEL_1_0_URI, "audio");
Map<QName, Serializable> aspectProperties = new HashMap<QName, Serializable>();
nodeService.addAspect(fileInfo.getNodeRef(), ASPECT_AUDIO, aspectProperties);
return fileInfo;
}
});
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
// get repository id
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
String objectIdStr = fileInfo.getNodeRef().toString();
Holder<String> objectId = new Holder<String>(objectIdStr);
// try to overflow the value
Object value = BigInteger.valueOf(Integer.MAX_VALUE + 1l);
Properties properties = new PropertiesImpl();
List<CmisExtensionElement> extensions = new ArrayList<CmisExtensionElement>();
CmisExtensionElement valueElem = new CmisExtensionElementImpl(CMISConnector.ALFRESCO_EXTENSION_NAMESPACE, "value", null, value.toString());
List<CmisExtensionElement> valueElems = new ArrayList<CmisExtensionElement>();
valueElems.add(valueElem);
List<CmisExtensionElement> children = new ArrayList<CmisExtensionElement>();
Map<String, String> attributes = new HashMap<String, String>();
attributes.put("propertyDefinitionId", "audio:trackNumber");
children.add(new CmisExtensionElementImpl(CMISConnector.ALFRESCO_EXTENSION_NAMESPACE, "propertyInteger", attributes, valueElems));
List<CmisExtensionElement> propertyValuesExtension = new ArrayList<CmisExtensionElement>();
propertyValuesExtension.add(new CmisExtensionElementImpl(CMISConnector.ALFRESCO_EXTENSION_NAMESPACE, CMISConnector.PROPERTIES, null, children));
CmisExtensionElement setAspectsExtension = new CmisExtensionElementImpl(CMISConnector.ALFRESCO_EXTENSION_NAMESPACE, CMISConnector.SET_ASPECTS, null, propertyValuesExtension);
extensions.add(setAspectsExtension);
properties.setExtensions(extensions);
// should throw a CMISConstraintException
cmisService.updateProperties(repositoryId, objectId, null, properties, null);
fail();
return null;
}
}, CmisVersion.CMIS_1_0);
}
catch(CmisConstraintException e)
{
assertTrue(e.getMessage().startsWith("Value is out of range for property"));
// ok
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
/**
* MNT-20139
* CmisConnector returns wrong values for changeLogToken and hasMoreItems
*/
@Test
public void testGetContentChanges()
{
setupAudit();
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
// create folders with files
createContent("testfolder" + GUID.generate(), "testdoc.txt" + GUID.generate(), false);
createContent("testfolder" + GUID.generate(), "testdoc.txt" + GUID.generate(), false);
createContent("testfolder" + GUID.generate(), "testdoc.txt" + GUID.generate(), false);
Holder<String> changeLogToken = new Holder<String>();
/*
* GetContentChanges with maxitems = 2 and null changeLogToken
* Check that changeLogToken should be the latest from the retrieved entries
*/
ObjectList ol = this.cmisConnector.getContentChanges(changeLogToken, new BigInteger("2"));
assertEquals(2, ol.getObjects().size());
assertEquals("ChangeLogToken should be latest from retrieved entries.", "2", changeLogToken.getValue());
assertTrue(ol.hasMoreItems());
/*
* GetContentChanges with maxitems = 2 and changeLogToken = 0
* Check that changeLogToken should be the latest from the retrieved entries
*/
changeLogToken.setValue(Integer.toString(0));
ol = this.cmisConnector.getContentChanges(changeLogToken, new BigInteger("2"));
assertEquals(2, ol.getObjects().size());
assertEquals("ChangeLogToken should be latest from retrieved entries.", "2", changeLogToken.getValue());
assertTrue(ol.hasMoreItems());
/*
* GetContentChanges with changeLogToken = maxChangeLogToken - 2
* Check that changeLogToken is not null when the latest entries (fromToken) are retrieved
*/
Long latestToken = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Long>()
{
public Long execute() throws Exception
{
return Long.parseLong(cmisConnector.getRepositoryInfo(CmisVersion.CMIS_1_1).getLatestChangeLogToken());
}
}, true, false);
Long fromToken = latestToken - 2;
changeLogToken.setValue(fromToken.toString());
ol = this.cmisConnector.getContentChanges(changeLogToken, new BigInteger("20"));
assertEquals(3, ol.getObjects().size());
assertNotNull(changeLogToken.getValue());
assertEquals("ChangeLogToken should be the latest from all entries.", latestToken.toString(), changeLogToken.getValue());
assertFalse(ol.hasMoreItems());
}
finally
{
auditSubsystem.destroy();
AuthenticationUtil.popAuthentication();
};
}
/**
* MNT-10223
* Check the IsLatestMajorVersion for a doc with minor version.
*/
@SuppressWarnings("unused")
@Test
public void testIsLatestMajorVersion()
{
final TestContext testContext = new TestContext();
// create simple text plain content
final PropertiesImpl properties = new PropertiesImpl();
String objectTypeId = "cmis:document";
properties.addProperty(new PropertyIdImpl(PropertyIds.OBJECT_TYPE_ID, objectTypeId));
String fileName = "textFile" + GUID.generate();
properties.addProperty(new PropertyStringImpl(PropertyIds.NAME, fileName));
final ContentStreamImpl contentStream = new ContentStreamImpl(fileName, MimetypeMap.MIMETYPE_TEXT_PLAIN, "Simple text plain document");
withCmisService(new CmisServiceCallback<String>() {
@Override
public String execute(CmisService cmisService) {
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
String objectId = cmisService.create(repositoryId, properties, repositoryHelper.getCompanyHome().getId(), contentStream, VersioningState.MINOR, null, null);
ObjectData cmidDoc = cmisService.getObject(repositoryId, objectId, null, true, IncludeRelationships.NONE, null, false, false, null);
List<PropertyData<?>> properties = cmidDoc.getProperties().getPropertyList();
boolean found = false;
PropertyData<?> propIsLatestMajorVersion = null;
for (PropertyData<?> property : properties)
{
if (property.getId().equals(PropertyIds.IS_LATEST_MAJOR_VERSION))
{
found = true;
propIsLatestMajorVersion = property;
break;
}
}
//properties..contains(CMISDictionaryModel.PROP_IS_LATEST_MAJOR_VERSION);
assertTrue("The CMISDictionaryModel.PROP_IS_LATEST_MAJOR_VERSION property was not found", found);
if (found)
{
assertFalse("The CMISDictionaryModel.PROP_IS_LATEST_MAJOR_VERSION should be false as minor version was created", (Boolean) propIsLatestMajorVersion.getValues().get(0));
}
return objectId;
}
});
}
/**
* ACE-33
*
* Cmis Item support
*/
@Test
public void testItems()
{
withCmisService(new CmisServiceCallback<String>() {
@Override
public String execute(CmisService cmisService) {
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
TypeDefinition def = cmisService.getTypeDefinition(repositoryId, "cmis:item", null);
assertNotNull("the cmis:item type is not defined", def);
@SuppressWarnings("unused")
TypeDefinition p = cmisService.getTypeDefinition(repositoryId, "I:cm:person", null);
assertNotNull("the I:cm:person type is not defined", def);
ObjectList result = cmisService.query(repositoryId, "select * from cm:person", Boolean.FALSE, Boolean.TRUE, IncludeRelationships.NONE, "", BigInteger.TEN, BigInteger.ZERO, null);
assertTrue("", result.getNumItems().intValue() > 0);
return "";
};
}, CmisVersion.CMIS_1_1);
}
/**
* MNT-11339 related test :
* Unable to create relationship between cmis:document and cmis:item
*/
@Test
public void testItemRelations()
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
final String TEST_NAME = "testItemRelations-";
final String FOLDER_NAME = TEST_NAME + "FOLDER" + GUID.generate();
final String DOCUMENT_NAME = TEST_NAME + "DOCUMENT" + GUID.generate();
final String CLIENT_NAME = "Some Test Client " + GUID.generate();
try
{
transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
/* Create folder within companyHome */
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, FOLDER_NAME, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, FOLDER_NAME);
assertNotNull(folderInfo);
// and document
FileInfo document = fileFolderService.create(folderInfo.getNodeRef(), DOCUMENT_NAME, ContentModel.TYPE_CONTENT);
assertNotNull(document);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, DOCUMENT_NAME);
return null;
}
});
withCmisService(new CmisServiceCallback<String>() {
@SuppressWarnings("unchecked")
@Override
public String execute(CmisService cmisService) {
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
// ensure there are custom type, aspect and association defined
TypeDefinition tpdfn = cmisService.getTypeDefinition(repositoryId, "I:sctst:client", null);
assertNotNull("the I:sctst:client type is not defined", tpdfn);
TypeDefinition aspectDfn = cmisService.getTypeDefinition(repositoryId, "P:sctst:clientRelated", null);
assertNotNull("the P:sctst:clientRelated aspect is not defined", aspectDfn);
TypeDefinition relDfn = cmisService.getTypeDefinition(repositoryId, "R:sctst:relatedClients", null);
assertNotNull("the R:sctst:relatedClients association is not defined", relDfn);
// create cmis:item within test folder
PropertiesImpl properties = new PropertiesImpl();
properties.addProperty(new PropertyIdImpl(PropertyIds.OBJECT_TYPE_ID, tpdfn.getId()));
properties.addProperty(new PropertyStringImpl(PropertyIds.NAME, CLIENT_NAME));
properties.addProperty(new PropertyStringImpl("sctst:clientId", "id" + GUID.generate()));
properties.addProperty(new PropertyStringImpl("sctst:clientName", CLIENT_NAME));
ObjectData folderData = cmisService.getObjectByPath(repositoryId, "/" + FOLDER_NAME, null, null, null, null, null, null, null);
cmisService.createItem(repositoryId, properties, folderData.getId(), null, null, null, null);
ObjectData contentData = cmisService.getObjectByPath(repositoryId, "/" + FOLDER_NAME + "/" + DOCUMENT_NAME, null, null, null, null, null, null, null);
// add test aspect sctst:clientRelated to document
Properties props = cmisService.getProperties(repositoryId, contentData.getId(), null, null);
PropertyData<?> propAspects = props.getProperties().get(PropertyIds.SECONDARY_OBJECT_TYPE_IDS);
@SuppressWarnings("rawtypes")
List aspects = propAspects.getValues();
aspects.add("P:sctst:clientRelated");
properties = new PropertiesImpl();
properties.addProperty(new PropertyStringImpl(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, aspects));
cmisService.updateProperties(repositoryId, new Holder<String>(contentData.getId()), null, properties, null);
// ensure document has sctst:clientRelated aspect applied
aspects = cmisService.getProperties(repositoryId, contentData.getId(), null, null).getProperties().get(PropertyIds.SECONDARY_OBJECT_TYPE_IDS).getValues();
assertTrue("P:sctst:clientRelated excpected", aspects.contains("P:sctst:clientRelated"));
ObjectData itemData = cmisService.getObjectByPath(repositoryId, "/" + FOLDER_NAME + "/" + CLIENT_NAME, null, null, null, null, null, null, null);
// create relationship between cmis:document and cmis:item
properties = new PropertiesImpl();
properties.addProperty(new PropertyIdImpl(PropertyIds.OBJECT_TYPE_ID, "R:sctst:relatedClients"));
properties.addProperty(new PropertyIdImpl(PropertyIds.SOURCE_ID, contentData.getId()));
properties.addProperty(new PropertyIdImpl(PropertyIds.TARGET_ID, itemData.getId()));
cmisService.createRelationship(repositoryId, properties, null, null, null, null);
return "";
};
}, CmisVersion.CMIS_1_1);
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
@Test
public void testMNT10529() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
final Pair<FileInfo, FileInfo> folderAndDocument = transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<Pair<FileInfo, FileInfo>>()
{
@Override
public Pair<FileInfo, FileInfo> execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
String folderName = GUID.generate();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
assertNotNull(folderInfo);
String docName = GUID.generate();
FileInfo document = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
assertNotNull(document);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, docName);
return new Pair<FileInfo, FileInfo>(folderInfo, document);
}
});
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertNotNull(repositories);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.iterator().next();
String repositoryId = repo.getId();
String objectIdStr = folderAndDocument.getFirst().getNodeRef().toString();
ObjectInFolderList children = cmisService.getChildren(repositoryId, objectIdStr, null, "cmis:name ASC", false, IncludeRelationships.NONE, null, false, null,
null, null);
assertChildren(folderAndDocument, children);
children = cmisService.getChildren(repositoryId, objectIdStr, null, "cmis:name ASC, cmis:creationDate ASC", false, IncludeRelationships.NONE, null, false,
null, null, null);
assertChildren(folderAndDocument, children);
children = cmisService.getChildren(repositoryId, objectIdStr, null, " cmis:name ASC", false, IncludeRelationships.NONE, null, false, null, null, null);
assertChildren(folderAndDocument, children);
children = cmisService.getChildren(repositoryId, objectIdStr, null, " cmis:name ASC, cmis:creationDate ASC ", false, IncludeRelationships.NONE, null,
false, null, null, null);
assertChildren(folderAndDocument, children);
return null;
}
private void assertChildren(final Pair<FileInfo, FileInfo> folderAndDocument, ObjectInFolderList children)
{
assertNotNull(children);
assertTrue(1 == children.getNumItems().longValue());
PropertyData<?> nameData = children.getObjects().iterator().next().getObject().getProperties().getProperties().get("cmis:name");
assertNotNull(nameData);
Object name = nameData.getValues().iterator().next();
assertEquals(folderAndDocument.getSecond().getName(), name);
}
}, CmisVersion.CMIS_1_0);
}
catch (CmisConstraintException e)
{
fail(e.toString());
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
@Category(RedundantTests.class)
@Test
public void mnt10548test() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
final Pair<FileInfo, FileInfo> folderAndDocument = transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<Pair<FileInfo, FileInfo>>()
{
private final static String TEST_NAME = "mnt10548test-";
@Override
public Pair<FileInfo, FileInfo> execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
/* Create folder within companyHome */
String folderName = TEST_NAME + GUID.generate();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
assertNotNull(folderInfo);
/* Create content */
String docName = TEST_NAME + GUID.generate();
FileInfo document = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
assertNotNull(document);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, docName);
/* Add some tags */
NodeRef nodeRef = document.getNodeRef();
taggingService.addTag(nodeRef, "tag1");
taggingService.addTag(nodeRef, "tag2");
taggingService.addTag(nodeRef, "tag3");
return new Pair<FileInfo, FileInfo>(folderInfo, document);
}
});
ObjectData objData = withCmisService(
new CmisServiceCallback<ObjectData>()
{
private static final String FILE_FOLDER_SEPARATOR = "/";
@Override
public ObjectData execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
String path = FILE_FOLDER_SEPARATOR + folderAndDocument.getFirst().getName() + FILE_FOLDER_SEPARATOR + folderAndDocument.getSecond().getName();
/* get CMIS object of document */
ObjectData objData = cmisService.getObjectByPath(repositoryId, path, null, false, null, null, false, false, null);
return objData;
}
}, CmisVersion.CMIS_1_1);
Map<String, PropertyData<?>> cmisProps = objData.getProperties().getProperties();
String taggable = ContentModel.ASPECT_TAGGABLE.getPrefixedQName(namespaceService).toPrefixString();
PropertyData<?> propData = cmisProps.get(taggable);
assertNotNull(propData);
List<?> props = propData.getValues();
assertTrue(props.size() == 3);
/* MNT-10548 fix : CMIS should return List of String, not List of NodeRef */
for(Object o : props)
{
assertTrue(o.getClass() + " found but String expected", o instanceof String);
}
}
/**
* MNT-8804 related test :
* Check CMISConnector.query for search nodes in environment with corrupted indexes
*/
@Test
public void testQueryNodesWithCorruptedIndexes()
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
final String TEST_NAME = "mnt8804test-";
final String docName = TEST_NAME + GUID.generate();
/* Create node */
final FileInfo document = transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<FileInfo>()
{
@Override
public FileInfo execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
/* Create folder within companyHome */
String folderName = TEST_NAME + GUID.generate();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
assertNotNull(folderInfo);
/* Create document to query */
FileInfo document = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
assertNotNull(document);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, docName);
return document;
}
});
final Pair<Long, NodeRef> nodePair = nodeDAO.getNodePair(document.getNodeRef());
/* delete node's metadata directly */
transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
Pair<Long, ChildAssociationRef> childAssocPair = nodeDAO.getPrimaryParentAssoc(nodePair.getFirst());
nodeDAO.deleteChildAssoc(childAssocPair.getFirst());
nodeDAO.deleteNode(nodePair.getFirst());
return null;
}
});
/* ensure the node does not exist */
assertTrue(!nodeService.exists(nodePair.getSecond()));
String queryString = "SELECT * FROM cmis:document WHERE cmis:name='" + docName + "'";
ObjectList resultList = cmisConnector.query(queryString, Boolean.FALSE, IncludeRelationships.NONE, "cmis:none", BigInteger.ONE, BigInteger.ZERO);
assertEquals(resultList.getNumItems(), BigInteger.ZERO);
// prepare cmis query
CMISQueryOptions options = new CMISQueryOptions(queryString, cmisConnector.getRootStoreRef());
CmisVersion cmisVersion = cmisConnector.getRequestCmisVersion();
options.setCmisVersion(cmisVersion);
options.setQueryMode(CMISQueryMode.CMS_WITH_ALFRESCO_EXTENSIONS);
options.setSkipCount(0);
options.setMaxItems(100);
/* make query bypassing CMISConnector */
org.alfresco.opencmis.search.CMISResultSet rs = cmisConnector.getOpenCMISQueryService().query(options);
assertEquals(rs.getNumberFound(), 0);
}
/**
* CMIS 1.0 aspect properties should provide the following CMIS attributes:
* propertyDefinitionId, displayName, localName, queryName
*/
@Test
public void testMNT10021() throws Exception
{
final String folderName = "testfolder." + GUID.generate();
final String docName = "testdoc.txt." + GUID.generate();
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
assertNotNull(folderInfo);
FileInfo document = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
assertNotNull(document);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, docName);
// lock adds aspects to the document with properties: lockIsDeep, lockOwner, lockType, expiryDate, lockLifetime
lockService.lock(document.getNodeRef(), LockType.READ_ONLY_LOCK, 0, true);
return null;
}
});
final ObjectData objectData = withCmisService(new CmisServiceCallback<ObjectData>()
{
@Override
public ObjectData execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
ObjectData objectData = cmisService.getObjectByPath(repositoryId, "/" + folderName + "/" + docName, null, true,
IncludeRelationships.NONE, null, false, true, null);
return objectData;
}
}, CmisVersion.CMIS_1_0);
List<CmisExtensionElement> propertyExtensionList = objectData.getProperties().getExtensions();
assertEquals("propertyExtensionList should be singletonList", propertyExtensionList.size(), 1);
List<CmisExtensionElement> extensions = propertyExtensionList.iterator().next().getChildren();
for (CmisExtensionElement extension : extensions)
{
if ("properties".equals(extension.getName()))
{
// check properties extension
List<CmisExtensionElement> propExtensions = extension.getChildren();
assertTrue("cmisObject should contain aspect properties", propExtensions.size() > 0);
for (CmisExtensionElement prop : propExtensions)
{
Map<String, String> cmisAspectProperty = prop.getAttributes();
Set<String> cmisAspectPropertyNames = cmisAspectProperty.keySet();
assertTrue("propertyDefinitionId attribute should be present", cmisAspectPropertyNames.contains("propertyDefinitionId"));
assertTrue("queryName attribute should be present", cmisAspectPropertyNames.contains("queryName"));
// optional values that are present for test document
assertTrue("displayName attribute should be present for property of test node", cmisAspectPropertyNames.contains("displayName"));
assertTrue("localName attribute should be present for property of test node", cmisAspectPropertyNames.contains("localName"));
assertEquals(cmisAspectPropertyNames.size(), 4);
// check values
for (String aspectPropertyName : cmisAspectPropertyNames)
{
String value = cmisAspectProperty.get(aspectPropertyName);
assertTrue("value for " + aspectPropertyName + " should be present", value != null && value.length() > 0);
}
}
}
}
}
catch (CmisConstraintException e)
{
fail(e.toString());
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
@Test
public void dictionaryTest()
{
TenantUtil.runAsUserTenant(new TenantRunAsWork<Void>()
{
@Override
public Void doWork() throws Exception
{
M2Model customModel = M2Model.createModel(
Thread.currentThread().getContextClassLoader().
getResourceAsStream("dictionary/dictionarydaotest_model1.xml"));
dictionaryDAO.putModel(customModel);
assertNotNull(cmisDictionaryService.findType("P:cm:dublincore"));
TypeDefinitionWrapper td = cmisDictionaryService.findType("D:daotest1:type1");
assertNotNull(td);
return null;
}
}, "user1", "tenant1");
TenantUtil.runAsUserTenant(new TenantRunAsWork<Void>()
{
@Override
public Void doWork() throws Exception
{
assertNotNull(cmisDictionaryService.findType("P:cm:dublincore"));
TypeDefinitionWrapper td = cmisDictionaryService.findType("D:daotest1:type1");
assertNull(td);
return null;
}
}, "user2", "tenant2");
}
/**
* MNT-13529: Just-installed Alfresco does not return a CMIS latestChangeLogToken
*
* @throws Exception
*/
@Test
public void testMNT13529() throws Exception
{
setupAudit();
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
// Delete the entries, it simulates just installed Alfresco for reproduce the issue
final Long appId = auditSubsystem.getAuditApplicationByName("CMISChangeLog").getApplicationId();
RetryingTransactionCallback<Void> deletedCallback = new RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
auditDAO.deleteAuditEntries(appId, null, null);
return null;
}
};
transactionService.getRetryingTransactionHelper().doInTransaction(deletedCallback);
// Retrieve initial latestChangeLogToken
final String initialChangeLogToken = withCmisService(new CmisServiceCallback<String>()
{
@Override
public String execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertNotNull(repositories);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.iterator().next();
return repo.getLatestChangeLogToken();
}
}, CmisVersion.CMIS_1_1);
assertNotNull(initialChangeLogToken);
assertEquals("0", initialChangeLogToken);
}
finally
{
auditSubsystem.destroy();
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
{
final String changeToken = withCmisService(new CmisServiceCallback<String>()
{
@Override
public String execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertNotNull(repositories);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.iterator().next();
return repo.getLatestChangeLogToken();
}
}, CmisVersion.CMIS_1_1);
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
// 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());
return null;
}
});
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertNotNull(repositories);
assertTrue(repositories.size() > 0);
String repositoryId = repositories.iterator().next().getId();
ObjectList changes = cmisService.getContentChanges(repositoryId, new Holder<String>(changeToken), Boolean.TRUE, null, Boolean.FALSE, Boolean.FALSE, BigInteger.valueOf(1000), null);
for (ObjectData od : changes.getObjects())
{
ChangeType changeType = od.getChangeEventInfo().getChangeType();
Object objectId = od.getProperties().getProperties().get("cmis:objectId").getValues().get(0);
assertFalse("CMISChangeEvent " + changeType + " should store short form of objectId " + objectId,
objectId.toString().contains(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE.toString()));
}
int expectAtLeast = changes.getObjects().size();
// We should also be able to query without passing in any limit
changes = cmisService.getContentChanges(repositoryId, new Holder<String>(changeToken), Boolean.TRUE, null, Boolean.FALSE, Boolean.FALSE, null, null);
assertTrue("Expected to still get changes", changes.getObjects().size() >= expectAtLeast);
// and zero
changes = cmisService.getContentChanges(repositoryId, new Holder<String>(changeToken), Boolean.TRUE, null, Boolean.FALSE, Boolean.FALSE, BigInteger.valueOf(0), null);
assertTrue("Expected to still get changes", changes.getObjects().size() >= expectAtLeast);
// and one
changes = cmisService.getContentChanges(repositoryId, new Holder<String>(changeToken), Boolean.TRUE, null, Boolean.FALSE, Boolean.FALSE, BigInteger.valueOf(1), null);
assertEquals("Expected to still get changes", changes.getObjects().size(), 1);
// Integery.MAX_VALUE must be handled
// This will limit the number to a sane value
changes = cmisService.getContentChanges(repositoryId, new Holder<String>(changeToken), Boolean.TRUE, null, Boolean.FALSE, Boolean.FALSE, BigInteger.valueOf(Integer.MAX_VALUE), null);
assertTrue("Expected to still get changes", changes.getObjects().size() >= expectAtLeast);
// but not negative
try
{
changes = cmisService.getContentChanges(repositoryId, new Holder<String>(changeToken), Boolean.TRUE, null, Boolean.FALSE, Boolean.FALSE, BigInteger.valueOf(-1), null);
fail("Negative maxItems is expected to fail");
}
catch (CmisInvalidArgumentException e)
{
// Expected
}
return null;
}
}, CmisVersion.CMIS_1_1);
}
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<Void> initAudit = new RetryingTransactionCallback<Void>()
{
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);
}
/**
* MNT-11727: move and rename operations should be shown as an UPDATE in the CMIS change log
*/
@Test
public void testMoveRenameWithCMISshouldBeAuditedAsUPDATE() throws Exception
{
// setUp audit subsystem
setupAudit();
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
assertTrue("Audit is not enabled", auditSubsystem.isAuditEnabled());
assertNotNull("CMIS audit is not enabled", auditSubsystem.getAuditApplicationByName("CMISChangeLog"));
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
String folder = GUID.generate();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folder, ContentModel.TYPE_FOLDER);
final String actualToken = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<String>()
{
public String execute() throws Exception
{
return cmisConnector.getRepositoryInfo(CmisVersion.CMIS_1_1).getLatestChangeLogToken();
}
}, true, false);
String content = GUID.generate();
FileInfo document = fileFolderService.create(folderInfo.getNodeRef(), content, ContentModel.TYPE_CONTENT);
assertNotNull(document);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, content);
Holder<String> changeLogToken = new Holder<String>();
changeLogToken.setValue(actualToken);
ObjectList changeLog = CMISTest.this.cmisConnector.getContentChanges(changeLogToken, new BigInteger("10"));
List<ObjectData> events = changeLog.getObjects();
int count = events.size();
// it should be 3 entries: 1 for previous folder create, 1 new CREATE (for document create)
// and 1 NEW UPDATE
assertEquals(3, count);
assertEquals(events.get(0).getProperties().getPropertyList().get(0).getValues().get(0), folderInfo.getNodeRef().getId());
assertEquals(events.get(0).getChangeEventInfo().getChangeType(), ChangeType.CREATED);
assertTrue(((String) events.get(1).getProperties().getPropertyList().get(0).getValues().get(0)).contains(document.getNodeRef().getId()));
assertEquals(events.get(1).getChangeEventInfo().getChangeType(), ChangeType.CREATED);
assertTrue(((String) events.get(2).getProperties().getPropertyList().get(0).getValues().get(0)).contains(document.getNodeRef().getId()));
assertEquals(events.get(2).getChangeEventInfo().getChangeType(), ChangeType.UPDATED);
// test rename
final String actualToken2 = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<String>()
{
public String execute() throws Exception
{
return cmisConnector.getRepositoryInfo(CmisVersion.CMIS_1_1).getLatestChangeLogToken();
}
}, true, false);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, content + "-updated");
changeLogToken = new Holder<String>();
changeLogToken.setValue(actualToken2);
changeLog = CMISTest.this.cmisConnector.getContentChanges(changeLogToken, new BigInteger("10"));
events = changeLog.getObjects();
count = events.size();
assertEquals(2, count);
assertEquals("Rename operation should be shown as an UPDATE in the CMIS change log", events.get(1).getChangeEventInfo().getChangeType(), ChangeType.UPDATED);
// test move
String targetFolder = GUID.generate();
FileInfo targetFolderInfo = fileFolderService.create(companyHomeNodeRef, targetFolder, ContentModel.TYPE_FOLDER);
final String actualToken3 = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<String>()
{
public String execute() throws Exception
{
return cmisConnector.getRepositoryInfo(CmisVersion.CMIS_1_1).getLatestChangeLogToken();
}
}, true, false);
nodeService.moveNode(document.getNodeRef(), targetFolderInfo.getNodeRef(), ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS);
changeLogToken = new Holder<String>();
changeLogToken.setValue(actualToken3);
changeLog = CMISTest.this.cmisConnector.getContentChanges(changeLogToken, new BigInteger("10"));
events = changeLog.getObjects();
count = events.size();
assertEquals(2, count);
assertEquals("Move operation should be shown as an UPDATE in the CMIS change log", events.get(1).getChangeEventInfo().getChangeType(), ChangeType.UPDATED);
}
finally
{
auditSubsystem.destroy();
AuthenticationUtil.popAuthentication();
}
}
/**
* MNT-11304: Test that Alfresco has no default boundaries for decimals
* @throws Exception
*/
@Test
public void testDecimalDefaultBoundaries() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
TypeDefinition decimalTypeDef = cmisService.getTypeDefinition(repositoryId, "D:tcdm:testdecimalstype", null);
PropertyDecimalDefinitionImpl floatNoBoundsTypeDef =
(PropertyDecimalDefinitionImpl)decimalTypeDef.getPropertyDefinitions().get("tcdm:float");
PropertyDecimalDefinitionImpl doubleNoBoundsTypeDef =
(PropertyDecimalDefinitionImpl)decimalTypeDef.getPropertyDefinitions().get("tcdm:double");
PropertyDecimalDefinitionImpl floatWithBoundsTypeDef =
(PropertyDecimalDefinitionImpl)decimalTypeDef.getPropertyDefinitions().get("tcdm:floatwithbounds");
PropertyDecimalDefinitionImpl doubleWithBoundsTypeDef =
(PropertyDecimalDefinitionImpl)decimalTypeDef.getPropertyDefinitions().get("tcdm:doublewithbounds");
// test that there is not default boundaries for decimals
assertNull(floatNoBoundsTypeDef.getMinValue());
assertNull(floatNoBoundsTypeDef.getMaxValue());
assertNull(doubleNoBoundsTypeDef.getMinValue());
assertNull(doubleNoBoundsTypeDef.getMaxValue());
// test for pre-defined boundaries
assertTrue(floatWithBoundsTypeDef.getMinValue().equals(BigDecimal.valueOf(-10f)));
assertTrue(floatWithBoundsTypeDef.getMaxValue().equals(BigDecimal.valueOf(10f)));
assertTrue(doubleWithBoundsTypeDef.getMinValue().equals(BigDecimal.valueOf(-10d)));
assertTrue(doubleWithBoundsTypeDef.getMaxValue().equals(BigDecimal.valueOf(10d)));
return null;
}
}, CmisVersion.CMIS_1_1);
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
/**
* MNT-11876 : Test that Alfresco CMIS 1.1 Implementation is returning aspect and aspect properties as extension data
* @throws Exception
*/
@Test
public void testExtensionDataIsReturnedViaCmis1_1() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
final String FOLDER = "testExtensionDataIsReturnedViaCmis1_1-" + GUID.generate();
final String CONTENT = FOLDER + "-file";
try
{
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
// create folder
FileInfo folderInfo = fileFolderService.create(repositoryHelper.getCompanyHome(), FOLDER, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, FOLDER);
assertNotNull(folderInfo);
// create document
FileInfo document = fileFolderService.create(folderInfo.getNodeRef(), CONTENT, ContentModel.TYPE_CONTENT);
assertNotNull(document);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, CONTENT);
// apply aspect with properties
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
props.put(ContentModel.PROP_LATITUDE, Double.valueOf(1.0d));
props.put(ContentModel.PROP_LONGITUDE, Double.valueOf(1.0d));
nodeService.addAspect(document.getNodeRef(), ContentModel.ASPECT_GEOGRAPHIC, props);
return null;
}
});
final ObjectData objectData = withCmisService(new CmisServiceCallback<ObjectData>()
{
@Override
public ObjectData execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
// get object data
ObjectData objectData = cmisService.getObjectByPath(repositoryId, "/" + FOLDER + "/" + CONTENT, null, true,
IncludeRelationships.NONE, null, false, true, null);
return objectData;
}
}, CmisVersion.CMIS_1_1);
// get extension data from object properties
List<CmisExtensionElement> extensions = objectData.getProperties().getExtensions().iterator().next().getChildren();
Set<String> appliedAspects = new HashSet<String>();
Set<String> aspectProperties = new HashSet<String>();
for (CmisExtensionElement extension : extensions)
{
if (CMISConnector.PROPERTIES.equals(extension.getName()))
{
// check properties extension
List<CmisExtensionElement> propExtensions = extension.getChildren();
assertTrue("cmisObject should contain aspect properties", propExtensions.size() > 0);
for (CmisExtensionElement prop : propExtensions)
{
Map<String, String> cmisAspectProperty = prop.getAttributes();
Set<String> cmisAspectPropertyNames = cmisAspectProperty.keySet();
assertTrue("propertyDefinitionId attribute should be present", cmisAspectPropertyNames.contains("propertyDefinitionId"));
aspectProperties.add(cmisAspectProperty.get("propertyDefinitionId"));
}
}
else if (CMISConnector.APPLIED_ASPECTS.equals(extension.getName()))
{
appliedAspects.add(extension.getValue());
}
}
// extension data should contain applied aspects and aspect properties
assertTrue("Extensions should contain " + ContentModel.ASPECT_GEOGRAPHIC, appliedAspects.contains("P:cm:geographic"));
assertTrue("Extensions should contain " + ContentModel.PROP_LATITUDE, aspectProperties.contains("cm:latitude"));
assertTrue("Extensions should contain " + ContentModel.PROP_LONGITUDE, aspectProperties.contains("cm:longitude"));
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
/**
* MNT-10165: Check that all concomitant basic CMIS permissions are deleted
* when permission is deleted vai CMIS 1.1 API. For Atom binding it applies
* new set of permissions instead of deleting the old ones.
*/
@Test
public void testRemoveACL() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
final String groupName = "group" + GUID.generate();
final String testGroup = PermissionService.GROUP_PREFIX + groupName;
try
{
// preconditions: create test document
if (!authorityService.authorityExists(testGroup))
{
authorityService.createAuthority(AuthorityType.GROUP, groupName);
}
final FileInfo document = transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<FileInfo>()
{
@Override
public FileInfo execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
String folderName = GUID.generate();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
assertNotNull(folderInfo);
String docName = GUID.generate();
FileInfo document = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
assertNotNull(document);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, docName);
return document;
}
});
Set<AccessPermission> permissions = permissionService.getAllSetPermissions(document.getNodeRef());
assertEquals(permissions.size(), 1);
AccessPermission current = permissions.iterator().next();
assertEquals(current.getAuthority(), "GROUP_EVERYONE");
assertEquals(current.getPermission(), "Consumer");
// add group1 with Coordinator permissions
permissionService.setPermission(document.getNodeRef(), testGroup, PermissionService.COORDINATOR, true);
permissions = permissionService.getAllSetPermissions(document.getNodeRef());
Map<String , String> docPermissions = new HashMap<String, String>();
for (AccessPermission permission : permissions)
{
docPermissions.put(permission.getAuthority(), permission.getPermission());
}
assertTrue(docPermissions.keySet().contains(testGroup));
assertEquals(docPermissions.get(testGroup), PermissionService.COORDINATOR);
// update permissions for group1 via CMIS 1.1 API
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertNotNull(repositories);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.iterator().next();
String repositoryId = repo.getId();
String docIdStr = document.getNodeRef().toString();
// when removing Coordinator ACE there are only inherited permissions
// so empty list of direct permissions is sent to be set
AccessControlListImpl acesToPut = new AccessControlListImpl();
List<Ace> acesList = Collections.emptyList();
acesToPut.setAces(acesList);
cmisService.applyAcl(repositoryId, docIdStr, acesToPut, AclPropagation.REPOSITORYDETERMINED);
return null;
}
}, CmisVersion.CMIS_1_1);
// check that permissions are the same as they were before Coordinator was added
permissions = permissionService.getAllSetPermissions(document.getNodeRef());
docPermissions = new HashMap<String, String>();
for (AccessPermission permission : permissions)
{
docPermissions.put(permission.getAuthority(), permission.getPermission());
}
assertFalse(docPermissions.keySet().contains(testGroup));
assertEquals(permissions.size(), 1);
current = permissions.iterator().next();
assertEquals(current.getAuthority(), "GROUP_EVERYONE");
assertEquals(current.getPermission(), "Consumer");
}
catch (CmisConstraintException e)
{
fail(e.toString());
}
finally
{
if (authorityService.authorityExists(testGroup))
{
authorityService.deleteAuthority(testGroup);
}
AuthenticationUtil.popAuthentication();
}
}
/**
* ACE-2904
*/
@Test
public void testACE2904()
{ // Basic CMIS Types // Additional types from Content Model
final String[] types = { "cmis:document", "cmis:relationship", "cmis:folder", "cmis:policy", "cmis:item", "R:cm:replaces", "P:cm:author", "I:cm:cmobject" };
final String[] displayNames = { "Document", "Relationship", "Folder", "Policy", "Item Type", "Replaces", "Author", "Object" };
final String[] descriptions = { "Document Type", "Relationship Type", "Folder Type", "Policy Type", "CMIS Item", "Replaces", "Author", "I:cm:cmobject" };
CmisServiceCallback<String> callback = new CmisServiceCallback<String>()
{
@Override
public String execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
for (int i = 0; i < types.length; i++)
{
TypeDefinition def = cmisService.getTypeDefinition(repositoryId, types[i], null);
assertNotNull("The " + types[i] + " type is not defined", def);
assertNotNull("The display name is incorrect. Please, refer to ACE-2904.", def.getDisplayName());
assertEquals("The display name is incorrect. Please, refer to ACE-2904.", def.getDisplayName(), displayNames[i]);
assertEquals("The description is incorrect. Please, refer to ACE-2904.", def.getDescription(), descriptions[i]);
for (PropertyDefinition<?> property : def.getPropertyDefinitions().values())
{
assertNotNull("Property definition dispaly name is incorrect. Please, refer to ACE-2904.", property.getDisplayName());
assertNotNull("Property definition description is incorrect. Please, refer to ACE-2904.", property.getDescription());
}
}
return "";
};
};
// Lets test types for cmis 1.1 and cmis 1.0
withCmisService(callback, CmisVersion.CMIS_1_1);
withCmisService(callback, CmisVersion.CMIS_1_0);
}
/**
* ACE-3322
*/
@Test
public void testACE3322()
{
final String[] types = { "cmis:document", "cmis:relationship", "cmis:folder", "cmis:item" };
CmisServiceCallback<String> callback = new CmisServiceCallback<String>()
{
@Override
public String execute(CmisService cmisService)
{
for (int i = 0; i < types.length; i++)
{
List<TypeDefinitionWrapper> baseTypes = cmisDictionaryService.getBaseTypes();
assertNotNull(baseTypes);
checkDefs(baseTypes);
List<TypeDefinitionWrapper> children = cmisDictionaryService.getChildren(types[i]);
assertNotNull(children);
// Check that children were updated
checkDefs(children);
}
return "";
};
private void checkDefs(List<TypeDefinitionWrapper> defs)
{
for (TypeDefinitionWrapper def : defs)
{
assertNotNull("Type definition was not updated. Please refer to ACE-3322", def.getTypeDefinition(false).getDisplayName());
assertNotNull("Type definition was not updated. Please refer to ACE-3322", def.getTypeDefinition(false).getDescription());
// Check that property's display name and description were updated
for (PropertyDefinitionWrapper property : def.getProperties())
{
assertNotNull("Display name is null", property.getPropertyDefinition().getDisplayName());
assertNotNull("Description is null", property.getPropertyDefinition().getDescription());
}
}
}
};
withCmisService(callback, CmisVersion.CMIS_1_1);
}
/**
* Test auto version behavior for setContentStream, deleteContentStream and appendContentStream according to ALF-21852.
*/
@Test
public void testSetDeleteAppendContentStreamVersioning() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
final String DOC1 = "documentProperties1-" + GUID.generate();
try
{
final FileInfo doc = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<FileInfo>()
{
@Override
public FileInfo execute() throws Throwable
{
FileInfo document;
// create document
document = fileFolderService.create(repositoryHelper.getCompanyHome(), DOC1, ContentModel.TYPE_CONTENT);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, DOC1);
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
props.put(ContentModel.PROP_TITLE, "Initial Title");
props.put(ContentModel.PROP_DESCRIPTION, "Initial Description");
nodeService.addAspect(document.getNodeRef(), ContentModel.ASPECT_TITLED, props);
// apply versionable aspect with properties
props = new HashMap<QName, Serializable>();
// ContentModel.PROP_INITIAL_VERSION always true
props.put(ContentModel.PROP_INITIAL_VERSION, true);
props.put(ContentModel.PROP_AUTO_VERSION, true);
props.put(ContentModel.PROP_AUTO_VERSION_PROPS, true);
versionService.ensureVersioningEnabled(document.getNodeRef(), props);
return document;
}
});
withCmisService(new CmisServiceCallback<Void>()
{
@Override public Void execute(CmisService cmisService)
{
final String documentNodeRefId = doc.getNodeRef().toString();
final String repositoryId = cmisService.getRepositoryInfos(null).get(0).getId();
ObjectInfo objInfoInitialVersion = cmisService.getObjectInfo(repositoryId, documentNodeRefId);
assertTrue("We had just created the document - it should be version 1.0", objInfoInitialVersion.getId().endsWith("1.0"));
ContentStreamImpl contentStream = new ContentStreamImpl(null, MimetypeMap.MIMETYPE_TEXT_PLAIN, "Content " + GUID.generate());
Holder<String> objectIdHolder = new Holder<>(documentNodeRefId);
// Test setContentStream
cmisService.setContentStream(repositoryId, objectIdHolder, true, null, contentStream, null);
assertTrue("The \"output\" parameter should returns the newly created version id: 1.1", objectIdHolder.getValue().endsWith("1.1"));
// we can use this new version id to get information about the cmis object
ObjectInfo objInfoAfterSetContentStream = cmisService.getObjectInfo(repositoryId, objectIdHolder.getValue());
assertTrue("The object info should reflect the version requested: 1.1", objInfoAfterSetContentStream.getId().endsWith("1.1"));
// Test deleteContentStream
cmisService.deleteContentStream(repositoryId, objectIdHolder, null, null);
assertTrue("The \"output\" parameter should returns the newly created version id: 1.2", objectIdHolder.getValue().endsWith("1.2"));
// we can use this new version id to get information about the cmis object
objInfoAfterSetContentStream = cmisService.getObjectInfo(repositoryId, objectIdHolder.getValue());
assertTrue("The object info should reflect the version requested: 1.2", objInfoAfterSetContentStream.getId().endsWith("1.2"));
// Test appendContentStream
cmisService.appendContentStream(repositoryId, objectIdHolder, null, contentStream, true, null);
assertTrue("The \"output\" parameter should returns the newly created version id: 1.3", objectIdHolder.getValue().endsWith("1.3"));
// we can use this new version id to get information about the cmis object
objInfoAfterSetContentStream = cmisService.getObjectInfo(repositoryId, objectIdHolder.getValue());
assertTrue("The object info should reflect the version requested: 1.3", objInfoAfterSetContentStream.getId().endsWith("1.3"));
return null;
}
}, CmisVersion.CMIS_1_1);
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
/**
* Test to ensure auto version behavior for update properties, set and delete content using both Alfresco and CMIS perspectives.
* Testing different combinations of <b>cm:initialVersion</b>, <b>cm:autoVersion</b> and <b>cm:autoVersionOnUpdateProps</b> properties
* <br>
* OnUpdateProperties MINOR version should be created if <b>cm:initialVersion</b> and <b>cm:autoVersionOnUpdateProps</b> are both TRUE
* <br>
* OnContentUpdate MINOR version should be created if <b>cm:initialVersion</b> and <b>cm:autoVersion</b> are both TRUE
*
* @throws Exception
*/
@Test
public void testUpdatePropertiesSetDeleteContentVersioning() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
final String FOLDER = "testUpdatePropertiesSetDeleteContentVersioning-" + GUID.generate();
final String DOC1 = "documentProperties1-" + GUID.generate();
final String DOC2 = "documentProperties2-" + GUID.generate();
final String DOC3 = "documentProperties3-" + GUID.generate();
final String DOC4 = "documentProperties4-" + GUID.generate();
try
{
final List<FileInfo> docs = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<List<FileInfo>>()
{
@Override
public List<FileInfo> execute() throws Throwable
{
// create folder
FileInfo folderInfo = fileFolderService.create(repositoryHelper.getCompanyHome(), FOLDER, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, FOLDER);
assertNotNull(folderInfo);
FileInfo document;
List<FileInfo> docs = new ArrayList<FileInfo>();
// create documents
document = fileFolderService.create(folderInfo.getNodeRef(), DOC1, ContentModel.TYPE_CONTENT);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, DOC1);
docs.add(document);
document = fileFolderService.create(folderInfo.getNodeRef(), DOC2, ContentModel.TYPE_CONTENT);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, DOC2);
docs.add(document);
document = fileFolderService.create(folderInfo.getNodeRef(), DOC3, ContentModel.TYPE_CONTENT);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, DOC3);
docs.add(document);
document = fileFolderService.create(folderInfo.getNodeRef(), DOC4, ContentModel.TYPE_CONTENT);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, DOC4);
docs.add(document);
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
props.put(ContentModel.PROP_TITLE, "Initial Title");
props.put(ContentModel.PROP_DESCRIPTION, "Initial Description");
for (FileInfo fileInfo : docs)
{
nodeService.addAspect(fileInfo.getNodeRef(), ContentModel.ASPECT_TITLED, props);
}
// apply versionable aspect with properties
props = new HashMap<QName, Serializable>();
// ContentModel.PROP_INITIAL_VERSION always true
props.put(ContentModel.PROP_INITIAL_VERSION, true);
props.put(ContentModel.PROP_AUTO_VERSION, false);
props.put(ContentModel.PROP_AUTO_VERSION_PROPS, false);
versionService.ensureVersioningEnabled(docs.get(0).getNodeRef(), props);
props.put(ContentModel.PROP_AUTO_VERSION, false);
props.put(ContentModel.PROP_AUTO_VERSION_PROPS, true);
versionService.ensureVersioningEnabled(docs.get(1).getNodeRef(), props);
props.put(ContentModel.PROP_AUTO_VERSION, true);
props.put(ContentModel.PROP_AUTO_VERSION_PROPS, false);
versionService.ensureVersioningEnabled(docs.get(2).getNodeRef(), props);
props.put(ContentModel.PROP_AUTO_VERSION, true);
props.put(ContentModel.PROP_AUTO_VERSION_PROPS, true);
versionService.ensureVersioningEnabled(docs.get(3).getNodeRef(), props);
return docs;
}
});
assertVersions(docs.get(0).getNodeRef(), "1.0", VersionType.MAJOR);
assertVersions(docs.get(1).getNodeRef(), "1.0", VersionType.MAJOR);
assertVersions(docs.get(2).getNodeRef(), "1.0", VersionType.MAJOR);
assertVersions(docs.get(3).getNodeRef(), "1.0", VersionType.MAJOR);
// update node properties using Alfresco
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<List<Void>>()
{
@Override
public List<Void> execute() throws Throwable
{
for (FileInfo fileInfo : docs)
{
Map<QName, Serializable> props = nodeService.getProperties(fileInfo.getNodeRef());
props.put(ContentModel.PROP_DESCRIPTION, "description-" + GUID.generate());
props.put(ContentModel.PROP_TITLE, "title-" + GUID.generate());
nodeService.setProperties(fileInfo.getNodeRef(), props);
}
return null;
}
});
assertVersions(docs.get(0).getNodeRef(), "1.0", VersionType.MAJOR);
assertVersions(docs.get(1).getNodeRef(), "1.1", VersionType.MINOR);
assertVersions(docs.get(2).getNodeRef(), "1.0", VersionType.MAJOR);
assertVersions(docs.get(3).getNodeRef(), "1.1", VersionType.MINOR);
// update properties using CMIS perspective
final String repositoryId = withCmisService(new CmisServiceCallback<String>()
{
@Override
public String execute(CmisService cmisService)
{
String repositoryId = cmisService.getRepositoryInfos(null).get(0).getId();
for (FileInfo fileInfo : docs)
{
PropertiesImpl properties = new PropertiesImpl();
properties.addProperty(new PropertyStringImpl(PropertyIds.DESCRIPTION, "description-" + GUID.generate()));
cmisService.updateProperties(repositoryId, new Holder<String>(fileInfo.getNodeRef().toString()), null, properties, null);
}
//This extra check was added due to MNT-16641.
{
PropertiesImpl properties = new PropertiesImpl();
properties.addProperty(new PropertyStringImpl(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, "P:cm:lockable"));
Set<QName> existingAspects = nodeService.getAspects(docs.get(0).getNodeRef());
cmisService.updateProperties(repositoryId,new Holder<String>(docs.get(0).getNodeRef().toString()), null, properties, null);
Set<QName> updatedAspects = nodeService.getAspects(docs.get(0).getNodeRef());
updatedAspects.removeAll(existingAspects);
assertEquals(ContentModel.ASPECT_LOCKABLE, updatedAspects.iterator().next());
}
return repositoryId;
}
}, CmisVersion.CMIS_1_1);
assertVersions(docs.get(0).getNodeRef(), "1.0", VersionType.MAJOR);
assertVersions(docs.get(1).getNodeRef(), "1.2", VersionType.MINOR);
assertVersions(docs.get(2).getNodeRef(), "1.0", VersionType.MAJOR);
assertVersions(docs.get(3).getNodeRef(), "1.2", VersionType.MINOR);
// CMIS setContentStream
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
for (FileInfo fileInfo : docs)
{
ContentStreamImpl contentStream = new ContentStreamImpl(null, MimetypeMap.MIMETYPE_TEXT_PLAIN, "Content " + GUID.generate());
cmisService.setContentStream(repositoryId, new Holder<String>(fileInfo.getNodeRef().toString()), true, null, contentStream, null);
}
return null;
}
}, CmisVersion.CMIS_1_1);
assertVersions(docs.get(0).getNodeRef(), "1.0", VersionType.MAJOR);
assertVersions(docs.get(1).getNodeRef(), "1.2", VersionType.MINOR);
assertVersions(docs.get(2).getNodeRef(), "1.1", VersionType.MINOR);
assertVersions(docs.get(3).getNodeRef(), "1.3", VersionType.MINOR);
// update content using Alfresco
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<List<Void>>()
{
@Override
public List<Void> execute() throws Throwable
{
for (FileInfo fileInfo : docs)
{
ContentWriter writer = contentService.getWriter(fileInfo.getNodeRef(), ContentModel.PROP_CONTENT, true);
writer.putContent("Content " + GUID.generate());
}
return null;
}
});
assertVersions(docs.get(0).getNodeRef(), "1.0", VersionType.MAJOR);
assertVersions(docs.get(1).getNodeRef(), "1.2", VersionType.MINOR);
assertVersions(docs.get(2).getNodeRef(), "1.2", VersionType.MINOR);
assertVersions(docs.get(3).getNodeRef(), "1.4", VersionType.MINOR);
// CMIS deleteContentStream
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
for (FileInfo fileInfo : docs)
{
cmisService.deleteContentStream(repositoryId, new Holder<String>(fileInfo.getNodeRef().toString()), null, null);
}
return null;
}
}, CmisVersion.CMIS_1_1);
assertVersions(docs.get(0).getNodeRef(), "1.0", VersionType.MAJOR);
assertVersions(docs.get(1).getNodeRef(), "1.2", VersionType.MINOR);
assertVersions(docs.get(2).getNodeRef(), "1.3", VersionType.MINOR);
assertVersions(docs.get(3).getNodeRef(), "1.5", VersionType.MINOR);
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
private void assertVersions(final NodeRef nodeRef, final String expectedVersionLabel, final VersionType expectedVersionType)
{
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<List<Void>>()
{
@Override
public List<Void> execute() throws Throwable
{
assertTrue("Node should be versionable", nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE));
Version version = versionService.getCurrentVersion(nodeRef);
assertNotNull(version);
assertEquals(expectedVersionLabel, version.getVersionLabel());
assertEquals(expectedVersionType, version.getVersionType());
return null;
}
});
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
String repositoryId = cmisService.getRepositoryInfos(null).get(0).getId();
ObjectData data =
cmisService.getObjectOfLatestVersion(repositoryId, nodeRef.toString(), null, Boolean.FALSE, null, null, null, null, null, null, null);
assertNotNull(data);
PropertyData<?> prop = data.getProperties().getProperties().get(PropertyIds.VERSION_LABEL);
Object versionLabelCmisValue = prop.getValues().get(0);
assertEquals(expectedVersionLabel, versionLabelCmisValue);
return null;
}
}, CmisVersion.CMIS_1_1);
}
/**
* Test to ensure that set of aspect returned by cmisService#getAllVersions for latest version is the same
* as for the object returned by cmisService#getObjectByPath.
*
* See <a href="https://issues.alfresco.com/jira/browse/MNT-9557">MNT-9557</a>
*/
@Test
public void testLastVersionOfVersionSeries()
{
CallContext context = new SimpleCallContext("admin", "admin", CmisVersion.CMIS_1_0);
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
final String FOLDER = "testUpdatePropertiesSetDeleteContentVersioning-" + GUID.generate(),
DOC = "documentProperties-" + GUID.generate();
try
{
final NodeRef nodeRef = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<NodeRef>()
{
@Override
public NodeRef execute() throws Throwable
{
// create folder
FileInfo folderInfo = fileFolderService.create(repositoryHelper.getCompanyHome(), FOLDER, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, FOLDER);
assertNotNull(folderInfo);
// create documents
FileInfo document = fileFolderService.create(folderInfo.getNodeRef(), DOC, ContentModel.TYPE_CONTENT);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, DOC);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_DESCRIPTION, "Initial doc");
return document.getNodeRef();
}
});
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
// make sure that there is no version history yet
assertNull(versionService.getVersionHistory(nodeRef));
// create a version
// turn off auto-versioning
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
props.put(ContentModel.PROP_INITIAL_VERSION, false);
props.put(ContentModel.PROP_AUTO_VERSION, false);
props.put(ContentModel.PROP_AUTO_VERSION_PROPS, false);
versionService.ensureVersioningEnabled(nodeRef, props);
return null;
}
});
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
assertNotNull(versionService.getVersionHistory(nodeRef));
// create another one version
versionService.createVersion(nodeRef, null);
return null;
}
});
final String NEW_DOC_NAME = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<String>()
{
@Override
public String execute() throws Throwable
{
// add aspect to the node
String newDocName = DOC + GUID.generate();
nodeService.addAspect(nodeRef, ContentModel.ASPECT_AUTHOR, null);
nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, newDocName);
return newDocName;
}
});
CmisService cmisService = factory.getService(context);
String repositoryId = cmisService.getRepositoryInfos(null).get(0).getId();
List<ObjectData> versions =
cmisService.getAllVersions(repositoryId, nodeRef.toString(), null, null, null, null);
assertNotNull(versions);
// get the latest version
ObjectData latestVersion = versions.get(0);
// get the object
ObjectData object =
// cmisService.getObjectOfLatestVersion(repositoryId, nodeRef.toString(), null, false, null, null, null, null, false, false, null);
cmisService.getObjectByPath(repositoryId, "/" + FOLDER + "/" + NEW_DOC_NAME, null, null, null, null, false, false, null);
assertNotNull(latestVersion);
assertNotNull(object);
Object objectDescriptionString = object.getProperties().getProperties().get("cmis:name").getValues().get(0);
Object latestVersionDescriptionString = latestVersion.getProperties().getProperties().get("cmis:name").getValues().get(0);
// ensure that node and latest version both have same description
assertEquals(objectDescriptionString, latestVersionDescriptionString);
Set<String> documentAspects = new HashSet<String>();
for (CmisExtensionElement cmisEE : object.getProperties().getExtensions().get(0).getChildren())
{
documentAspects.add(cmisEE.getValue());
}
Set<String> latestVersionAspects = new HashSet<String>();
for (CmisExtensionElement cmisEE : latestVersion.getProperties().getExtensions().get(0).getChildren())
{
latestVersionAspects.add(cmisEE.getValue());
}
// ensure that node and latest version both have the same set of aspects
assertEquals(latestVersionAspects, documentAspects);
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
/**
* Test to ensure that versioning properties have default values defined in Alfresco content model.
* Testing <b>cm:initialVersion</b>, <b>cm:autoVersion</b> and <b>cm:autoVersionOnUpdateProps</b> properties
*
* @throws Exception
*/
@Test
public void testVersioningPropertiesHaveDefaultValue() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
// Create document via CMIS
final NodeRef documentNodeRef = withCmisService(new CmisServiceCallback<NodeRef>()
{
@Override
public NodeRef execute(CmisService cmisService)
{
String repositoryId = cmisService.getRepositoryInfos(null).get(0).getId();
String rootNodeId = cmisService.getObjectByPath(repositoryId, "/", null, true, IncludeRelationships.NONE, null, false, true, null).getId();
Collection<PropertyData<?>> propsList = new ArrayList<PropertyData<?>>();
propsList.add(new PropertyStringImpl(PropertyIds.NAME, "Folder-" + GUID.generate()));
propsList.add(new PropertyIdImpl(PropertyIds.OBJECT_TYPE_ID, "cmis:folder"));
String folderId = cmisService.createFolder(repositoryId, new PropertiesImpl(propsList), rootNodeId, null, null, null, null);
propsList = new ArrayList<PropertyData<?>>();
propsList.add(new PropertyStringImpl(PropertyIds.NAME, "File-" + GUID.generate()));
propsList.add(new PropertyIdImpl(PropertyIds.OBJECT_TYPE_ID, "cmis:document"));
String nodeId = cmisService.createDocument(repositoryId, new PropertiesImpl(propsList), folderId, null, null, null, null, null, null);
return new NodeRef(nodeId.substring(0, nodeId.indexOf(';')));
}
}, CmisVersion.CMIS_1_1);
// check versioning properties
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<List<Void>>()
{
@Override
public List<Void> execute() throws Throwable
{
assertTrue(nodeService.exists(documentNodeRef));
assertTrue(nodeService.hasAspect(documentNodeRef, ContentModel.ASPECT_VERSIONABLE));
AspectDefinition ad = dictionaryService.getAspect(ContentModel.ASPECT_VERSIONABLE);
Map<QName, org.alfresco.service.cmr.dictionary.PropertyDefinition> properties = ad.getProperties();
for (QName qName : new QName[] {ContentModel.PROP_INITIAL_VERSION, ContentModel.PROP_AUTO_VERSION, ContentModel.PROP_AUTO_VERSION_PROPS})
{
Serializable property = nodeService.getProperty(documentNodeRef, qName);
assertNotNull(property);
org.alfresco.service.cmr.dictionary.PropertyDefinition pd = properties.get(qName);
assertNotNull(pd.getDefaultValue());
assertEquals(property, Boolean.parseBoolean(pd.getDefaultValue()));
}
return null;
}
});
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
@Test
public void testCreateDocWithVersioningStateNone() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
// get repository id
final String repositoryId = withCmisService(new CmisServiceCallback<String>()
{
@Override
public String execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
final String repositoryId = repo.getId();
return repositoryId;
}
}, CmisVersion.CMIS_1_1);
final NodeRef documentNodeRef = withCmisService(new CmisServiceCallback<NodeRef>()
{
@Override
public NodeRef execute(CmisService cmisService)
{
final PropertiesImpl properties = new PropertiesImpl();
String objectTypeId = "cmis:document";
properties.addProperty(new PropertyIdImpl(PropertyIds.OBJECT_TYPE_ID, objectTypeId));
String fileName = "textFile" + GUID.generate();
properties.addProperty(new PropertyStringImpl(PropertyIds.NAME, fileName));
final ContentStreamImpl contentStream = new ContentStreamImpl(fileName, MimetypeMap.MIMETYPE_TEXT_PLAIN, "Simple text plain document");
String nodeId = cmisService.create(repositoryId, properties, repositoryHelper.getCompanyHome().getId(), contentStream, VersioningState.NONE, null, null);
return new NodeRef(nodeId.substring(0, nodeId.indexOf(';')));
}
}, CmisVersion.CMIS_1_1);
// check versioning properties
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<List<Void>>()
{
@Override
public List<Void> execute() throws Throwable
{
assertTrue(nodeService.exists(documentNodeRef));
assertFalse(nodeService.hasAspect(documentNodeRef, ContentModel.ASPECT_VERSIONABLE));
return null;
}
});
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
/**
* MNT-14951: Test that the list of parents can be retrieved for a folder.
*/
@Test
public void testCMISGetObjectParents() throws Exception
{
// setUp audit subsystem
setupAudit();
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
final NodeRef folderWithTwoParents = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<NodeRef>()
{
@Override
public NodeRef execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
String folder1 = GUID.generate();
FileInfo folderInfo1 = fileFolderService.create(companyHomeNodeRef, folder1, ContentModel.TYPE_FOLDER);
assertNotNull(folderInfo1);
String folder2 = GUID.generate();
FileInfo folderInfo2 = fileFolderService.create(companyHomeNodeRef, folder2, ContentModel.TYPE_FOLDER);
assertNotNull(folderInfo2);
// Create folder11 as a subfolder of folder1
String folder11 = GUID.generate();
FileInfo folderInfo11 = fileFolderService.create(folderInfo1.getNodeRef(), folder11, ContentModel.TYPE_FOLDER);
assertNotNull(folderInfo11);
// Add folder2 as second parent for folder11
nodeService.addChild(folderInfo2.getNodeRef(), folderInfo11.getNodeRef(), ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS);
return folderInfo11.getNodeRef();
}
});
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertNotNull(repositories);
assertTrue(repositories.size() > 0);
String repositoryId = repositories.iterator().next().getId();
List<ObjectParentData> parents = cmisService.getObjectParents(repositoryId, folderWithTwoParents.getId(), null, Boolean.FALSE, IncludeRelationships.NONE,
"cmis:none", Boolean.FALSE, null);
// Check if the second parent was also returned.
assertEquals(2, parents.size());
return null;
}
}, CmisVersion.CMIS_1_1);
}
finally
{
auditSubsystem.destroy();
AuthenticationUtil.popAuthentication();
}
}
/*
* REPO-3627 / MNT-19630: CMIS: Unable to call getAllVersions() if node is checked out and if binding type is WSDL
*
* For WS binding the getAllVersions call is made with null objectId
*/
@Test
public void getAllVersionsWithNullObjectId()
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
// Create folder with file
String folderName = "testfolder" + GUID.generate();
String docName = "testdoc.txt" + GUID.generate();
NodeRef folderRef = createContent(folderName, docName, false).getNodeRef();
List<FileInfo> folderFileList = fileFolderService.list(folderRef);
final NodeRef fileRef = folderFileList.get(0).getNodeRef();
// Create new version for file
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
// create a new version
versionService.createVersion(fileRef, null);
return null;
}
});
// Checkout document and get all versions
List<ObjectData> versions = withCmisService(new CmisServiceCallback<List<ObjectData>>()
{
@Override
public List<ObjectData> execute(CmisService cmisService)
{
String repositoryId = cmisService.getRepositoryInfos(null).get(0).getId();
ObjectData objectData = cmisService.getObjectByPath(repositoryId, "/" + folderName + "/" + docName, null, true, IncludeRelationships.NONE, null,
false, true, null);
// Checkout
Holder<String> objectId = new Holder<String>(objectData.getId());
cmisService.checkOut(repositoryId, objectId, null, new Holder<Boolean>(true));
// Call get all versions with null objectId
List<ObjectData> versions = cmisService.getAllVersions(repositoryId, null, fileRef.toString(), null, null, null);
return versions;
}
});
// Check that the correct versions are retrieved
assertEquals(2, versions.size());
assertEquals(versions.get(0).getProperties().getProperties().get("cmis:versionLabel").getFirstValue(), "pwc");
assertEquals(versions.get(1).getProperties().getProperties().get("cmis:versionLabel").getFirstValue(), "0.1");
}
}