/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* 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 .
*/
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.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator;
import org.alfresco.repo.action.executer.AddFeaturesActionExecuter;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.action.ActionCondition;
import org.alfresco.service.cmr.action.ActionService;
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.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
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.tagging.TaggingService;
import org.alfresco.service.cmr.version.VersionService;
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.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.AllowableActions;
import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement;
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.Properties;
import org.apache.chemistry.opencmis.commons.data.PropertyData;
import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.enums.Action;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
import org.apache.chemistry.opencmis.commons.enums.VersioningState;
import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
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.PropertiesImpl;
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.spi.Holder;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.extensions.webscripts.GUID;
/**
* OpenCMIS tests.
*
* @author steveglover
*
*/
public class CMISTest
{
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 Repository repositoryHelper;
private VersionService versionService;
private LockService lockService;
private TaggingService taggingService;
private NamespaceService namespaceService;
private AlfrescoCmisServiceFactory factory;
private ActionService actionService;
private RuleService ruleService;
private CMISConnector cmisConnector;
/**
* 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 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 parameters)
{
serviceFactory.init(parameters);
}
@Override
public void destroy()
{
}
@Override
public CmisService getService(CallContext context)
{
return serviceFactory.getService(context);
}
}
private static class SimpleCallContext implements CallContext
{
private final Map contextMap = new HashMap();
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;
}
/* (non-Javadoc)
* @see org.apache.chemistry.opencmis.commons.server.CallContext#encryptTempFiles()
*/
@Override
public boolean encryptTempFiles()
{
// TODO Auto-generated method stub
return false;
}
/* (non-Javadoc)
* @see org.apache.chemistry.opencmis.commons.server.CallContext#getCmisVersion()
*/
@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.versionService = (VersionService) ctx.getBean("versionService");
this.lockService = (LockService) ctx.getBean("lockService");
this.repositoryHelper = (Repository)ctx.getBean("repositoryHelper");
this.factory = (AlfrescoCmisServiceFactory)ctx.getBean("CMISServiceFactory");
this.cmisConnector = (CMISConnector) ctx.getBean("CMISConnector");
}
private FileInfo createContent(final String folderName, final String docName, final boolean isRule)
{
final FileInfo folderInfo = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
{
@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);
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 conditionProps = new HashMap();
conditionProps.put(ComparePropertyValueEvaluator.PARAM_VALUE, ".txt");
Map actionProps = new HashMap();
actionProps.put(AddFeaturesActionExecuter.PARAM_ASPECT_NAME, ContentModel.ASPECT_VERSIONABLE);
List ruleTypes = new ArrayList(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 withCmisService(CmisServiceCallback callback)
{
return withCmisService(callback, CmisVersion.CMIS_1_0);
}
private T withCmisService(CmisServiceCallback 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 execute(CmisService cmisService);
}
/**
* ALF-18006 Test content mimetype auto-detection into CmisStreamInterceptor when "Content-Type" is not defined.
*/
@Test
public void testContentMimeTypeDetection()
{
// get repository id
List repositories = withCmisService(new CmisServiceCallback>()
{
@Override
public List execute(CmisService cmisService)
{
List 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()
{
@Override
public String execute(CmisService cmisService)
{
String objectId = cmisService.create(repositoryId, properties, repositoryHelper.getCompanyHome().getId(), contentStream, VersioningState.MAJOR, null, null);
return objectId;
}
});
final Holder objectIdHolder = new Holder(objectId);
final String path = "/" + fileName;
// create content stream with undefined mimetype and file name
{
final ContentStreamImpl contentStreamHTML = new ContentStreamImpl(null, null, " Hello Test html