RM-1635: Recordable Version Store Service Prototype

* integration tests to ensure recorded version retireves the state of the versioned content accurately
 * various improvements to satisfy tests



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@81055 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2014-08-25 06:08:06 +00:00
parent a64f4db528
commit c0c2d3ca39
25 changed files with 1043 additions and 187 deletions

View File

@@ -70,6 +70,10 @@
<title>Record Node Reference</title> <title>Record Node Reference</title>
<type>d:noderef</type> <type>d:noderef</type>
<index enabled="false"/> <index enabled="false"/>
</property><property name="rmv:frozenOwner">
<title>Frozen Owner</title>
<type>d:text</type>
<index enabled="false"/>
</property> </property>
</properties> </properties>
</aspect> </aspect>

View File

@@ -18,6 +18,9 @@
<property name="namespaceService" ref="NamespaceService"/> <property name="namespaceService" ref="NamespaceService"/>
</bean> </bean>
<!-- Authentication Helper -->
<bean name="rm.authenticationUtil" class="org.alfresco.module.org_alfresco_module_rm.util.AuthenticationUtil"/>
<!-- Import extended repository context --> <!-- Import extended repository context -->
<import resource="classpath:alfresco/module/org_alfresco_module_rm/extended-repository-context.xml"/> <import resource="classpath:alfresco/module/org_alfresco_module_rm/extended-repository-context.xml"/>

View File

@@ -31,6 +31,7 @@
<bean id="baseService" abstract="true"> <bean id="baseService" abstract="true">
<property name="nodeService" ref="NodeService"/> <property name="nodeService" ref="NodeService"/>
<property name="dictionaryService" ref="DictionaryService"/> <property name="dictionaryService" ref="DictionaryService"/>
<property name="authenticationUtil" ref="rm.authenticationUtil"/>
</bean> </bean>
<!-- Records Management Service Registry --> <!-- Records Management Service Registry -->
@@ -1086,6 +1087,8 @@
org.alfresco.module.org_alfresco_module_rm.record.RecordService.disablePropertyEditableCheck=RM_ALLOW org.alfresco.module.org_alfresco_module_rm.record.RecordService.disablePropertyEditableCheck=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.record.RecordService.enablePropertyEditableCheck=RM_ALLOW org.alfresco.module.org_alfresco_module_rm.record.RecordService.enablePropertyEditableCheck=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.record.RecordService.getRecordMetaDataAspects=RM_ALLOW org.alfresco.module.org_alfresco_module_rm.record.RecordService.getRecordMetaDataAspects=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.record.RecordService.isRecordMetadataAspect=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.record.RecordService.isRecordMetadataProperty=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.record.RecordService.getRecordMetadataAspects=RM.Read.0 org.alfresco.module.org_alfresco_module_rm.record.RecordService.getRecordMetadataAspects=RM.Read.0
org.alfresco.module.org_alfresco_module_rm.record.RecordService.isRecord=ACL_ALLOW,RM_ALLOW org.alfresco.module.org_alfresco_module_rm.record.RecordService.isRecord=ACL_ALLOW,RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.record.RecordService.isDeclared=RM.Read.0 org.alfresco.module.org_alfresco_module_rm.record.RecordService.isDeclared=RM.Read.0

View File

@@ -16,6 +16,10 @@
<bean id="rm.versionService" abstract="true" class="org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionServiceImpl"> <bean id="rm.versionService" abstract="true" class="org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionServiceImpl">
<property name="filePlanService" ref="FilePlanService" /> <property name="filePlanService" ref="FilePlanService" />
<property name="fileFolderService" ref="fileFolderService" /> <property name="fileFolderService" ref="fileFolderService" />
<property name="extendedPermissionService" ref="ExtendedPermissionService" />
<property name="ownableService" ref="OwnableService" />
<property name="extendedSecurityService" ref="ExtendedSecurityService" />
<property name="authenticationUtil" ref="rm.authenticationUtil" />
</bean> </bean>
<bean class="org.alfresco.module.org_alfresco_module_rm.util.BeanExtender"> <bean class="org.alfresco.module.org_alfresco_module_rm.util.BeanExtender">
<property name="beanName" value="versionService" /> <property name="beanName" value="versionService" />
@@ -24,6 +28,7 @@
<!-- extended version node service bean definition --> <!-- extended version node service bean definition -->
<bean id="rm.versionNodeService" abstract="true" class="org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionNodeServiceImpl"> <bean id="rm.versionNodeService" abstract="true" class="org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionNodeServiceImpl">
<property name="recordService" ref="RecordService" />
</bean> </bean>
<bean class="org.alfresco.module.org_alfresco_module_rm.util.BeanExtender"> <bean class="org.alfresco.module.org_alfresco_module_rm.util.BeanExtender">
<property name="beanName" value="versionNodeService" /> <property name="beanName" value="versionNodeService" />

View File

@@ -50,6 +50,7 @@ rm.methodsecurity.org.alfresco.service.cmr.repository.NodeService.getChildAssocs
rm.methodsecurity.org.alfresco.service.cmr.repository.NodeService.getNodeRef=RM.Read.0 rm.methodsecurity.org.alfresco.service.cmr.repository.NodeService.getNodeRef=RM.Read.0
rm.methodsecurity.org.alfresco.service.cmr.repository.NodeService.getChildAssocsByPropertyValue=RM.Read.0,AFTER_RM.FilterNode rm.methodsecurity.org.alfresco.service.cmr.repository.NodeService.getChildAssocsByPropertyValue=RM.Read.0,AFTER_RM.FilterNode
rm.methodsecurity.org.alfresco.service.cmr.repository.NodeService.countChildAssocs=RM.Read.0 rm.methodsecurity.org.alfresco.service.cmr.repository.NodeService.countChildAssocs=RM.Read.0
rm.methodsecurity.org.alfresco.service.cmr.repository.NodeService.getNodeAclId=RM.Read.0
rm.methodsecurity.org.alfresco.service.cmr.repository.NodeService.*=RM_DENY rm.methodsecurity.org.alfresco.service.cmr.repository.NodeService.*=RM_DENY
## File Folder Service ## File Folder Service

View File

@@ -195,7 +195,7 @@ public class HoldServiceImpl extends ServiceBaseImpl
}; };
// run as system user // run as system user
runAsSystem(work); authenticationUtil.runAsSystem(work);
} }
} }
@@ -561,7 +561,7 @@ public class HoldServiceImpl extends ServiceBaseImpl
if (!getHeld(hold).contains(nodeRef)) if (!getHeld(hold).contains(nodeRef))
{ {
// run as system to ensure we have all the appropriate permissions to perform the manipulations we require // run as system to ensure we have all the appropriate permissions to perform the manipulations we require
runAsSystem(new RunAsWork<Void>() authenticationUtil.runAsSystem(new RunAsWork<Void>()
{ {
@Override @Override
public Void doWork() public Void doWork()
@@ -684,7 +684,7 @@ public class HoldServiceImpl extends ServiceBaseImpl
{ {
// run as system so we don't run into further permission issues // run as system so we don't run into further permission issues
// we already know we have to have the correct capability to get here // we already know we have to have the correct capability to get here
runAsSystem(new RunAsWork<Void>() authenticationUtil.runAsSystem(new RunAsWork<Void>()
{ {
@Override @Override
public Void doWork() public Void doWork()
@@ -703,7 +703,7 @@ public class HoldServiceImpl extends ServiceBaseImpl
} }
// run as system as we can't be sure if have remove aspect rights on node // run as system as we can't be sure if have remove aspect rights on node
runAsSystem(new RunAsWork<Void>() authenticationUtil.runAsSystem(new RunAsWork<Void>()
{ {
@Override @Override
public Void doWork() public Void doWork()

View File

@@ -79,6 +79,29 @@ public interface RecordService
*/ */
@Deprecated @Deprecated
Set<QName> getRecordMetaDataAspects(); Set<QName> getRecordMetaDataAspects();
/**
* Indicates whether the provided aspect is a registered record meta-data
* aspect.
*
* @param aspect aspect {@link QName}
* @return boolean true if the aspect is a registered record meta-data aspect, false otherwise
*
* @since 2.3
*/
boolean isRecordMetadataAspect(QName aspect);
/**
* Indicates whther the provided property is declared on a registered record
* meta-data aspect.
*
* @param property property {@link QName}
* @return boolean true if the property is declared on a registered record meta-data aspect,
* false otherwise
*
* @since 2.3
*/
boolean isRecordMetadataProperty(QName property);
/** /**
* Gets a list of all the record metadata aspects relevant to the file plan type of the * Gets a list of all the record metadata aspects relevant to the file plan type of the

View File

@@ -47,9 +47,11 @@ import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.model.security.ModelAccessDeniedException; import org.alfresco.module.org_alfresco_module_rm.model.security.ModelAccessDeniedException;
import org.alfresco.module.org_alfresco_module_rm.notification.RecordsManagementNotificationHelper; import org.alfresco.module.org_alfresco_module_rm.notification.RecordsManagementNotificationHelper;
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService; import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;
import org.alfresco.module.org_alfresco_module_rm.report.ReportModel;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.role.Role; import org.alfresco.module.org_alfresco_module_rm.role.Role;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel;
import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency; import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.ClassPolicyDelegate; import org.alfresco.repo.policy.ClassPolicyDelegate;
@@ -136,10 +138,12 @@ public class RecordServiceImpl extends BaseBehaviourBean
}; };
/** record model URI's */ /** record model URI's */
private static final String[] RECORD_MODEL_URIS = new String[] public static final String[] RECORD_MODEL_URIS = new String[]
{ {
RM_URI, RM_URI,
RM_CUSTOM_URI, RM_CUSTOM_URI,
ReportModel.RMR_URI,
RecordableVersionModel.RMV_URI,
DOD5015Model.DOD_URI DOD5015Model.DOD_URI
}; };
@@ -682,6 +686,35 @@ public class RecordServiceImpl extends BaseBehaviourBean
return getRecordMetadataAspects(TYPE_FILE_PLAN); return getRecordMetadataAspects(TYPE_FILE_PLAN);
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#isRecordMetadataAspect(org.alfresco.service.namespace.QName)
*/
@Override
public boolean isRecordMetadataAspect(QName aspect)
{
return getRecordMetadataAspectsMap().containsKey(aspect);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#isRecordMetadataProperty(org.alfresco.service.namespace.QName)
*/
@Override
public boolean isRecordMetadataProperty(QName property)
{
boolean result = false;
PropertyDefinition propertyDefinition = dictionaryService.getProperty(property);
if (propertyDefinition != null)
{
ClassDefinition classDefinition = propertyDefinition.getContainerClass();
if (classDefinition != null &&
getRecordMetadataAspectsMap().containsKey(classDefinition.getName()))
{
result = true;
}
}
return result;
}
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#getRecordMetaDataAspects(org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#getRecordMetaDataAspects(org.alfresco.service.cmr.repository.NodeRef)
*/ */

View File

@@ -20,6 +20,7 @@ package org.alfresco.module.org_alfresco_module_rm.security;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -31,6 +32,7 @@ import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl; import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.service.namespace.RegexQNamePattern;
@@ -236,18 +238,24 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
// get the reference count // get the reference count
Map<String, Integer> referenceCountMap = (Map<String, Integer>)nodeService.getProperty(filePlan, propertyName); Map<String, Integer> referenceCountMap = (Map<String, Integer>)nodeService.getProperty(filePlan, propertyName);
// set of assigned authorities
Set<String> assignedAuthorities = new HashSet<String>(authorities.size());
for (String authority : authorities) for (String authority : authorities)
{ {
if ((!authority.equals(PermissionService.ALL_AUTHORITIES) && !authority.equals(PermissionService.OWNER_AUTHORITY)) && if ((!authority.equals(PermissionService.ALL_AUTHORITIES) &&
!authority.equals(PermissionService.OWNER_AUTHORITY)) &&
!AuthorityType.ROLE.equals(AuthorityType.getAuthorityType(authority)) &&
(referenceCountMap == null || !referenceCountMap.containsKey(authority))) (referenceCountMap == null || !referenceCountMap.containsKey(authority)))
{ {
// add the authority to the role // add the authority to the role
filePlanRoleService.assignRoleToAuthority(filePlan, roleName, authority); filePlanRoleService.assignRoleToAuthority(filePlan, roleName, authority);
assignedAuthorities.add(authority);
} }
} }
// update the reference count // update the reference count
nodeService.setProperty(filePlan, propertyName, (Serializable)addToMap(referenceCountMap, authorities)); nodeService.setProperty(filePlan, propertyName, (Serializable)addToMap(referenceCountMap, assignedAuthorities));
} }
} }

View File

@@ -225,7 +225,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
if (nodeService.exists(parent)) if (nodeService.exists(parent))
{ {
runAsSystem(new AuthenticationUtil.RunAsWork<Object>() authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>()
{ {
public Object doWork() public Object doWork()
{ {
@@ -300,7 +300,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
*/ */
public void onAddRecord(final NodeRef record, final QName aspectTypeQName) public void onAddRecord(final NodeRef record, final QName aspectTypeQName)
{ {
runAsSystem(new AuthenticationUtil.RunAsWork<Object>() authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>()
{ {
public Object doWork() public Object doWork()
{ {
@@ -375,7 +375,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
{ {
if (nodeService.exists(nodeRef)) if (nodeService.exists(nodeRef))
{ {
runAsSystem(new AuthenticationUtil.RunAsWork<Object>() authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>()
{ {
public Object doWork() public Object doWork()
{ {
@@ -410,7 +410,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
ParameterCheck.mandatory("authority", authority); ParameterCheck.mandatory("authority", authority);
ParameterCheck.mandatory("permission", permission); ParameterCheck.mandatory("permission", permission);
runAsSystem(new AuthenticationUtil.RunAsWork<Object>() authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>()
{ {
public Void doWork() public Void doWork()
{ {
@@ -557,7 +557,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
*/ */
public void deletePermission(final NodeRef nodeRef, final String authority, final String permission) public void deletePermission(final NodeRef nodeRef, final String authority, final String permission)
{ {
runAsSystem(new AuthenticationUtil.RunAsWork<Object>() authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>()
{ {
public Void doWork() public Void doWork()
{ {

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2005-2014 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.util;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
/**
* Helper bean to allow injection of AuthenticationUtil methods.
* <p>
* Useful when testing using mocks.
*
* @author Roy Wetherall
* @since 2.3
*/
public class AuthenticationUtil
{
/**
* Helper method that executed work as system user.
* <p>
* Useful when testing using mocks.
*
* @see org.alfresco.repo.security.authentication.AuthenticationUtil#runAsSystem(RunAsWork, String)
*/
public <R> R runAsSystem(RunAsWork<R> runAsWork)
{
return org.alfresco.repo.security.authentication.AuthenticationUtil.runAsSystem(runAsWork);
}
/**
* Helper method that executed work as given user.
* <p>
* Useful when testing using mocks.
*
* @see org.alfresco.repo.security.authentication.AuthenticationUtil#runAs(RunAsWork, String)
*/
public <R> R runAs(RunAsWork<R> runAsWork, String uid)
{
return org.alfresco.repo.security.authentication.AuthenticationUtil.runAs(runAsWork, uid);
}
/**
* Helper method that gets the fully authenticated user.
* <p>
* Useful when testing using mocks.
*
* @see org.alfresco.repo.security.authentication.AuthenticationUtil#getFullyAuthenticatedUser()
*/
public String getFullyAuthenticatedUser()
{
return org.alfresco.repo.security.authentication.AuthenticationUtil.getFullyAuthenticatedUser();
}
/**
* Helper method that gets the admin user name.
* <p>
* Usefule when testing using mocks.
*
* @see org.alfresco.repo.security.authentication.AuthenticationUtil#getAdminUserName()
*/
public String getAdminUserName()
{
return org.alfresco.repo.security.authentication.AuthenticationUtil.getAdminUserName();
}
}

View File

@@ -26,8 +26,6 @@ import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanComponentKind
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService; import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.TransactionalResourceHelper; import org.alfresco.repo.transaction.TransactionalResourceHelper;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
@@ -58,6 +56,9 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
/** internal node service */ /** internal node service */
private NodeService internalNodeService; private NodeService internalNodeService;
/** authentication helper */
protected AuthenticationUtil authenticationUtil;
/** /**
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
@@ -84,6 +85,14 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
this.dictionaryService = dictionaryService; this.dictionaryService = dictionaryService;
} }
/**
* @param authenticationUtil authentication util helper
*/
public void setAuthenticationUtil(AuthenticationUtil authenticationUtil)
{
this.authenticationUtil = authenticationUtil;
}
/** /**
* Helper to get internal node service. * Helper to get internal node service.
* <p> * <p>
@@ -470,30 +479,4 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
result.add(nodeService.getType(nodeRef)); result.add(nodeService.getType(nodeRef));
return result; return result;
} }
/**
* Helper method that executed work as system user.
* <p>
* Useful when testing using mocks.
*
* @param runAsWork work to execute as system user
* @return
*/
public <R> R runAsSystem(RunAsWork<R> runAsWork)
{
return AuthenticationUtil.runAsSystem(runAsWork);
}
/**
* Helper method that executed work as given user.
* <p>
* Useful when testing using mocks.
*
* @param runAsWork work to execute as given user
* @return
*/
public <R> R runAs(RunAsWork<R> runAsWork, String uid)
{
return AuthenticationUtil.runAs(runAsWork, uid);
}
} }

View File

@@ -40,4 +40,5 @@ public interface RecordableVersionModel
/** recorded version aspect */ /** recorded version aspect */
public QName ASPECT_RECORDED_VERSION = QName.createQName(RMV_URI, "recordedVersion"); public QName ASPECT_RECORDED_VERSION = QName.createQName(RMV_URI, "recordedVersion");
public QName PROP_RECORD_NODE_REF = QName.createQName(RMV_URI, "recordNodeRef"); public QName PROP_RECORD_NODE_REF = QName.createQName(RMV_URI, "recordNodeRef");
public QName PROP_FROZEN_OWNER = QName.createQName(RMV_URI, "frozenOwner");
} }

View File

@@ -19,17 +19,27 @@
package org.alfresco.module.org_alfresco_module_rm.version; package org.alfresco.module.org_alfresco_module_rm.version;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImpl;
import org.alfresco.repo.version.Node2ServiceImpl; import org.alfresco.repo.version.Node2ServiceImpl;
import org.alfresco.repo.version.Version2Model;
import org.alfresco.repo.version.common.VersionUtil; import org.alfresco.repo.version.common.VersionUtil;
import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.apache.commons.lang.ArrayUtils;
/** /**
* Extended version node service implementation that supports the retrieval of
* recorded version state.
* *
* @author Roy Wetherall * @author Roy Wetherall
* @since 2.3 * @since 2.3
@@ -37,16 +47,31 @@ import org.alfresco.service.namespace.QName;
public class RecordableVersionNodeServiceImpl extends Node2ServiceImpl public class RecordableVersionNodeServiceImpl extends Node2ServiceImpl
implements RecordableVersionModel implements RecordableVersionModel
{ {
/** record service */
private RecordService recordService;
/**
* @param recordService record service
*/
public void setRecordService(RecordService recordService)
{
this.recordService = recordService;
}
/**
* @see org.alfresco.repo.version.Node2ServiceImpl#getProperties(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override @Override
public Map<QName, Serializable> getProperties(NodeRef nodeRef) throws InvalidNodeRefException public Map<QName, Serializable> getProperties(NodeRef nodeRef) throws InvalidNodeRefException
{ {
// TODO only supported for Version2
NodeRef converted = VersionUtil.convertNodeRef(nodeRef); NodeRef converted = VersionUtil.convertNodeRef(nodeRef);
if (dbNodeService.hasAspect(converted, ASPECT_RECORDED_VERSION)) if (dbNodeService.hasAspect(converted, ASPECT_RECORDED_VERSION))
{ {
NodeRef record = (NodeRef)dbNodeService.getProperty(converted, PROP_RECORD_NODE_REF); NodeRef record = (NodeRef)dbNodeService.getProperty(converted, PROP_RECORD_NODE_REF);
Map<QName, Serializable> properties = dbNodeService.getProperties(record); Map<QName, Serializable> properties = dbNodeService.getProperties(record);
return processProperties(properties); return processProperties(converted, properties);
} }
else else
{ {
@@ -54,18 +79,153 @@ public class RecordableVersionNodeServiceImpl extends Node2ServiceImpl
} }
} }
protected Map<QName, Serializable> processProperties(Map<QName, Serializable> properties) /**
* Process properties map before returning as frozen state.
*
* @param properties properties map
* @return {@link Map}<{@link QName}, {@link Serializable}> processed property map
*/
protected Map<QName, Serializable> processProperties(NodeRef version, Map<QName, Serializable> properties)
{ {
Map<QName, Serializable> cloneProperties = new HashMap<QName, Serializable>(properties);
// revert modified record name // revert modified record name
properties.put(ContentModel.PROP_NAME, properties.get(RecordsManagementModel.PROP_ORIGIONAL_NAME)); properties.put(ContentModel.PROP_NAME, properties.get(RecordsManagementModel.PROP_ORIGIONAL_NAME));
// remove all rma, rmc, rmr and rmv properties // remove all rma, rmc, rmr and rmv properties
for (QName property : cloneProperties.keySet())
// remove any properties relating to custom record-meta data {
if (!PROP_RECORDABLE_VERSION_POLICY.equals(property) &&
!PROP_FILE_PLAN.equals(property) &&
(recordService.isRecordMetadataProperty(property) ||
ArrayUtils.contains(RecordServiceImpl.RECORD_MODEL_URIS, property.getNamespaceURI())))
{
properties.remove(property);
}
}
// do standard property processing // do standard property processing
VersionUtil.convertFrozenToOriginalProps(properties); processVersionProperties(version, properties);
return properties; return properties;
} }
/**
* Process version properties.
*
* @param version version node reference
* @param properties properties map
*/
protected void processVersionProperties(NodeRef version, Map<QName, Serializable> properties) throws InvalidNodeRefException
{
// get version properties
Map<QName, Serializable> versionProperties = dbNodeService.getProperties(version);
if (versionProperties != null)
{
String versionLabel = (String)versionProperties.get(Version2Model.PROP_QNAME_VERSION_LABEL);
properties.put(ContentModel.PROP_VERSION_LABEL, versionLabel);
// Convert frozen sys:referenceable properties
NodeRef nodeRef = (NodeRef)versionProperties.get(Version2Model.PROP_QNAME_FROZEN_NODE_REF);
if (nodeRef != null)
{
properties.put(ContentModel.PROP_STORE_PROTOCOL, nodeRef.getStoreRef().getProtocol());
properties.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier());
properties.put(ContentModel.PROP_NODE_UUID, nodeRef.getId());
}
Long dbid = (Long)versionProperties.get(Version2Model.PROP_QNAME_FROZEN_NODE_DBID);
properties.put(ContentModel.PROP_NODE_DBID, dbid);
// Convert frozen cm:auditable properties
String creator = (String)versionProperties.get(Version2Model.PROP_QNAME_FROZEN_CREATOR);
if (creator != null)
{
properties.put(ContentModel.PROP_CREATOR, creator);
}
Date created = (Date)versionProperties.get(Version2Model.PROP_QNAME_FROZEN_CREATED);
if (created != null)
{
properties.put(ContentModel.PROP_CREATED, created);
}
// TODO - check use-cases for get version, revert, restore ....
String modifier = (String)versionProperties.get(Version2Model.PROP_QNAME_FROZEN_MODIFIER);
if (modifier != null)
{
properties.put(ContentModel.PROP_MODIFIER, modifier);
}
Date modified = (Date)versionProperties.get(Version2Model.PROP_QNAME_FROZEN_MODIFIED);
if (modified != null)
{
properties.put(ContentModel.PROP_MODIFIED, modified);
}
Date accessed = (Date)versionProperties.get(Version2Model.PROP_QNAME_FROZEN_ACCESSED);
if (accessed != null)
{
properties.put(ContentModel.PROP_ACCESSED, accessed);
}
String owner = (String)versionProperties.get(PROP_FROZEN_OWNER);
if (owner != null)
{
properties.put(ContentModel.PROP_OWNER, owner);
}
}
}
/**
* @see org.alfresco.repo.version.Node2ServiceImpl#getAspects(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public Set<QName> getAspects(NodeRef nodeRef) throws InvalidNodeRefException
{
// TODO only supported for Version2
NodeRef converted = VersionUtil.convertNodeRef(nodeRef);
if (dbNodeService.hasAspect(converted, ASPECT_RECORDED_VERSION))
{
NodeRef record = (NodeRef)dbNodeService.getProperty(converted, PROP_RECORD_NODE_REF);
Set<QName> aspects = dbNodeService.getAspects(record);
return processAspects(aspects);
}
else
{
return super.getAspects(nodeRef);
}
}
/**
* Process frozen aspects.
*
* @param aspects aspect set
* @return {@link Set}<{@link QName}> processed aspect set
*/
protected Set<QName> processAspects(Set<QName> aspects)
{
Set<QName> result = new HashSet<QName>(aspects);
// remove version aspects
result.remove(ASPECT_VERSION);
result.remove(ASPECT_RECORDED_VERSION);
// remove rm aspects
for (QName aspect : aspects)
{
if (!ASPECT_VERSIONABLE.equals(aspect) &&
(recordService.isRecordMetadataAspect(aspect) ||
ArrayUtils.contains(RecordServiceImpl.RECORD_MODEL_URIS, aspect.getNamespaceURI())))
{
result.remove(aspect);
}
}
// remove custom record meta-data aspects
return result;
}
} }

View File

@@ -21,20 +21,29 @@ package org.alfresco.module.org_alfresco_module_rm.version;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
import org.alfresco.module.org_alfresco_module_rm.util.AuthenticationUtil;
import org.alfresco.repo.policy.PolicyScope; import org.alfresco.repo.policy.PolicyScope;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.security.permissions.impl.ExtendedPermissionService;
import org.alfresco.repo.version.Version2Model; import org.alfresco.repo.version.Version2Model;
import org.alfresco.repo.version.Version2ServiceImpl; import org.alfresco.repo.version.Version2ServiceImpl;
import org.alfresco.repo.version.VersionModel; import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException; import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.OwnableService;
import org.alfresco.service.cmr.version.ReservedVersionNameException; import org.alfresco.service.cmr.version.ReservedVersionNameException;
import org.alfresco.service.cmr.version.Version; import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionType; import org.alfresco.service.cmr.version.VersionType;
@@ -64,6 +73,18 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
/** file folder service */ /** file folder service */
protected FileFolderService fileFolderService; protected FileFolderService fileFolderService;
/** extended permission service */
protected ExtendedPermissionService extendedPermissionService;
/** ownable service */
protected OwnableService ownableService;
/** extended security service */
protected ExtendedSecurityService extendedSecurityService;
/** authentication util helper */
protected AuthenticationUtil authenticationUtil;
/** /**
* @param filePlanService file plan service * @param filePlanService file plan service
*/ */
@@ -80,6 +101,38 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
this.fileFolderService = fileFolderService; this.fileFolderService = fileFolderService;
} }
/**
* @param extendedPermissionService extended permission service
*/
public void setExtendedPermissionService(ExtendedPermissionService extendedPermissionService)
{
this.extendedPermissionService = extendedPermissionService;
}
/**
* @param ownableService ownable service
*/
public void setOwnableService(OwnableService ownableService)
{
this.ownableService = ownableService;
}
/**
* @param extendedSecurityService extended security service
*/
public void setExtendedSecurityService(ExtendedSecurityService extendedSecurityService)
{
this.extendedSecurityService = extendedSecurityService;
}
/**
* @param authenticationUtil authentication util helper
*/
public void setAuthenticationUtil(AuthenticationUtil authenticationUtil)
{
this.authenticationUtil = authenticationUtil;
}
/** /**
* @see org.alfresco.repo.version.Version2ServiceImpl#createVersion(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, int) * @see org.alfresco.repo.version.Version2ServiceImpl#createVersion(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, int)
*/ */
@@ -128,9 +181,8 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
} }
/** /**
* * @param nodeRef node reference
* @param nodeRef * @return {@link NodeRef} associated file plan, default if none
* @return
*/ */
private NodeRef getFilePlan(NodeRef nodeRef) private NodeRef getFilePlan(NodeRef nodeRef)
{ {
@@ -143,8 +195,7 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
} }
/** /**
* * @return {@link NodeRef} default file plan, exception if none
* @return
*/ */
private NodeRef getFilePlan() private NodeRef getFilePlan()
{ {
@@ -212,6 +263,7 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
} }
/** /**
* Creates a new recorded version
* *
* @param sourceTypeRef * @param sourceTypeRef
* @param versionHistoryRef * @param versionHistoryRef
@@ -240,61 +292,35 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
try try
{ {
// get the destination file plan // get the destination file plan
NodeRef filePlan = (NodeRef)versionProperties.get(KEY_FILE_PLAN); final NodeRef filePlan = (NodeRef)versionProperties.get(KEY_FILE_PLAN);
if (filePlan == null) if (filePlan == null)
{ {
throw new AlfrescoRuntimeException("Can't create a new recorded version, because no file plan has been specified in the version properties."); throw new AlfrescoRuntimeException("Can't create a new recorded version, because no file plan has been specified in the version properties.");
} }
// get the unfiled record folder
final NodeRef unfiledRecordFolder = filePlanService.getUnfiledContainer(filePlan);
// create a copy of the source node and place in the file plan // create a copy of the source node and place in the file plan
final NodeRef nodeRef = (NodeRef)standardVersionProperties.get(Version2Model.PROP_QNAME_FROZEN_NODE_REF); final NodeRef nodeRef = (NodeRef)standardVersionProperties.get(Version2Model.PROP_QNAME_FROZEN_NODE_REF);
// copy version state and create record // create record
NodeRef record = null; NodeRef record = createRecord(nodeRef, filePlan);
try
{
FileInfo recordInfo = fileFolderService.copy(nodeRef, unfiledRecordFolder, null);
record = recordInfo.getNodeRef();
}
catch (FileNotFoundException e)
{
throw new AlfrescoRuntimeException("Can't create recorded version, because copy fails.", e);
}
// set up extended permissions
// TODO
// create version nodeRef // create version nodeRef
ChildAssociationRef childAssocRef = this.dbNodeService.createNode( ChildAssociationRef childAssocRef = dbNodeService.createNode(
versionHistoryRef, versionHistoryRef,
Version2Model.CHILD_QNAME_VERSIONS, Version2Model.CHILD_QNAME_VERSIONS,
QName.createQName(Version2Model.NAMESPACE_URI, Version2Model.CHILD_VERSIONS + "-" + versionNumber), // TODO - testing - note: all children (of a versioned node) will have the same version number, maybe replace with a version sequence of some sort 001-...00n QName.createQName(Version2Model.NAMESPACE_URI, Version2Model.CHILD_VERSIONS + "-" + versionNumber), // TODO - testing - note: all children (of a versioned node) will have the same version number, maybe replace with a version sequence of some sort 001-...00n
sourceTypeRef, sourceTypeRef,
null); null);
versionNodeRef = childAssocRef.getChildRef(); versionNodeRef = childAssocRef.getChildRef();
// NOTE: special ML case - see also MultilingualContentServiceImpl.makeMLContainer
// if (sourceTypeRef.equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
// {
// // Set the permissions to allow anything by anyone
// permissionService.setPermission(
// versionNodeRef,
// PermissionService.ALL_AUTHORITIES,
// PermissionService.ALL_PERMISSIONS, true);
// permissionService.setPermission(
// versionNodeRef,
// AuthenticationUtil.getGuestUserName(),
// PermissionService.ALL_PERMISSIONS, true);
// }
// add aspect with the standard version properties to the 'version' node // add aspect with the standard version properties to the 'version' node
nodeService.addAspect(versionNodeRef, Version2Model.ASPECT_VERSION, standardVersionProperties); nodeService.addAspect(versionNodeRef, Version2Model.ASPECT_VERSION, standardVersionProperties);
// add the recordedVersion aspect with link to record // add the recordedVersion aspect with link to record
nodeService.addAspect(versionNodeRef, ASPECT_RECORDED_VERSION, Collections.singletonMap(PROP_RECORD_NODE_REF, (Serializable)record)); nodeService.addAspect(versionNodeRef, ASPECT_RECORDED_VERSION, Collections.singletonMap(PROP_RECORD_NODE_REF, (Serializable)record));
// freeze auditable aspect information
freezeAuditableAspect(nodeRef, versionNodeRef);
} }
finally finally
{ {
@@ -318,6 +344,118 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
return versionNodeRef; return versionNodeRef;
} }
/**
* Create record from current version
*
* @param nodeRef state to freeze
* @param filePlan destination file plan
* @return {@link NodeRef} versioned record
*/
private NodeRef createRecord(final NodeRef nodeRef, final NodeRef filePlan)
{
return authenticationUtil.runAs(new RunAsWork<NodeRef>()
{
public NodeRef doWork() throws Exception
{
// get the unfiled record folder
final NodeRef unfiledRecordFolder = filePlanService.getUnfiledContainer(filePlan);
// get the documents readers
Long aclId = dbNodeService.getNodeAclId(nodeRef);
Set<String> readers = extendedPermissionService.getReaders(aclId);
Set<String> writers = extendedPermissionService.getWriters(aclId);
// add the current owner to the list of extended writers
Set<String> modifiedWrtiers = new HashSet<String>(writers);
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_OWNABLE))
{
String owner = ownableService.getOwner(nodeRef);
if (owner != null && !owner.isEmpty() && !owner.equals(OwnableService.NO_OWNER))
{
modifiedWrtiers.add(owner);
}
}
// add the current user as extended writer
modifiedWrtiers.add(authenticationUtil.getFullyAuthenticatedUser());
// copy version state and create record
NodeRef record = null;
try
{
List<AssociationRef> originalAssocs = null;
if (dbNodeService.hasAspect(nodeRef, ContentModel.ASPECT_COPIEDFROM))
{
// take a note of any copyFrom information already on the node
originalAssocs = dbNodeService.getTargetAssocs(nodeRef, ContentModel.ASSOC_ORIGINAL);
}
// create a copy of the original state and add it to the unfiled record container
FileInfo recordInfo = fileFolderService.copy(nodeRef, unfiledRecordFolder, null);
record = recordInfo.getNodeRef();
// remove added copy assocs
List<AssociationRef> recordAssocs = dbNodeService.getTargetAssocs(record, ContentModel.ASSOC_ORIGINAL);
for (AssociationRef recordAssoc : recordAssocs)
{
dbNodeService.removeAssociation(
recordAssoc.getSourceRef(),
recordAssoc.getTargetRef(),
ContentModel.ASSOC_ORIGINAL);
}
// re-add origional assocs or remove aspect
if (originalAssocs == null)
{
dbNodeService.removeAspect(record, ContentModel.ASPECT_COPIEDFROM);
}
else
{
for (AssociationRef originalAssoc : originalAssocs)
{
dbNodeService.createAssociation(originalAssoc.getSourceRef(), originalAssoc.getTargetRef(), ContentModel.ASSOC_ORIGINAL);
}
}
}
catch (FileNotFoundException e)
{
throw new AlfrescoRuntimeException("Can't create recorded version, because copy fails.", e);
}
// set extended security on record
extendedSecurityService.addExtendedSecurity(record, readers, writers);
return record;
}
}, authenticationUtil.getAdminUserName());
}
/**
* Freezes audit aspect properties.
*
* @param nodeRef
* @param versionNodeRef
*/
private void freezeAuditableAspect(NodeRef nodeRef, NodeRef versionNodeRef)
{
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_AUDITABLE))
{
Map<QName, Serializable> properties = dbNodeService.getProperties(nodeRef);
dbNodeService.setProperty(versionNodeRef, Version2Model.PROP_QNAME_FROZEN_CREATOR, properties.get(ContentModel.PROP_CREATOR));
dbNodeService.setProperty(versionNodeRef, Version2Model.PROP_QNAME_FROZEN_CREATED, properties.get(ContentModel.PROP_CREATED));
dbNodeService.setProperty(versionNodeRef, Version2Model.PROP_QNAME_FROZEN_MODIFIER, properties.get(ContentModel.PROP_MODIFIER));
dbNodeService.setProperty(versionNodeRef, Version2Model.PROP_QNAME_FROZEN_MODIFIED, properties.get(ContentModel.PROP_MODIFIED));
dbNodeService.setProperty(versionNodeRef, Version2Model.PROP_QNAME_FROZEN_ACCESSED, properties.get(ContentModel.PROP_ACCESSED));
if (properties.get(ContentModel.PROP_OWNER) != null)
{
dbNodeService.setProperty(versionNodeRef, PROP_FROZEN_OWNER, properties.get(ContentModel.PROP_OWNER));
}
}
}
/**
* @see org.alfresco.repo.version.Version2ServiceImpl#getVersion(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override @Override
protected Version getVersion(NodeRef versionRef) protected Version getVersion(NodeRef versionRef)
{ {

View File

@@ -59,7 +59,7 @@ public class MoveRecordFolderTest extends BaseRMTestCase
*/ */
public void testMoveRecordFolderBeforeCutOffFolderLevelDisposition() throws Exception public void testMoveRecordFolderBeforeCutOffFolderLevelDisposition() throws Exception
{ {
doBehaviourDrivenTest(new BehaviourDrivenTest(false) doBehaviourDrivenTest(new BehaviourDrivenTest(null, false)
{ {
NodeRef recordFolder; NodeRef recordFolder;
NodeRef destinationRecordCategory; NodeRef destinationRecordCategory;
@@ -141,7 +141,7 @@ public class MoveRecordFolderTest extends BaseRMTestCase
*/ */
public void testMoveRecordFolderBeforeCutOffIntoAFolderWithNoDisposition() throws Exception public void testMoveRecordFolderBeforeCutOffIntoAFolderWithNoDisposition() throws Exception
{ {
doBehaviourDrivenTest(new BehaviourDrivenTest(false) doBehaviourDrivenTest(new BehaviourDrivenTest(null, false)
{ {
NodeRef recordFolder; NodeRef recordFolder;
NodeRef destinationRecordCategory; NodeRef destinationRecordCategory;
@@ -217,7 +217,7 @@ public class MoveRecordFolderTest extends BaseRMTestCase
*/ */
public void testMoveRecordFolderWithRecordsBeforeCutOffRecordLevelDisposition() throws Exception public void testMoveRecordFolderWithRecordsBeforeCutOffRecordLevelDisposition() throws Exception
{ {
doBehaviourDrivenTest(new BehaviourDrivenTest(false) doBehaviourDrivenTest(new BehaviourDrivenTest(null, false)
{ {
NodeRef record; NodeRef record;
NodeRef recordFolder; NodeRef recordFolder;

View File

@@ -22,93 +22,153 @@ import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.alfresco.model.ContentModel; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; import org.alfresco.module.org_alfresco_module_rm.test.util.TestModel;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionServiceImpl; import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionServiceImpl;
import org.alfresco.repo.version.VersionModel; import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version; import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionType; import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.PropertyMap;
/** /**
* * AdHoc Recordable Versions Integration Test
* *
* @author Roy Wetherall * @author Roy Wetherall
* @since 2.3 * @since 2.3
*/ */
public class AdHocRecordableVersions extends BaseRMTestCase implements RecordableVersionModel public class AdHocRecordableVersions extends RecordableVersionsBaseTest
{ {
private static final QName QNAME_PUBLISHER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "publisher"); /**
private static final QName QNAME_SUBJECT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "subject"); * Adhoc recorded version creation, with no policy defined as site collaborator
*/
private static final String DESCRIPTION = "description";
private static final String PUBLISHER = "publisher";
private static final String SUBJECT = "subject";
@Override
protected boolean isCollaborationSiteTest()
{
return true;
}
public void testRecordAdHocVersionNoPolicy() public void testRecordAdHocVersionNoPolicy()
{ {
doBehaviourDrivenTest(new BehaviourDrivenTest() doBehaviourDrivenTest(new BehaviourDrivenTest(dmCollaborator)
{ {
private Version version; private Map<String, Serializable> versionProperties;
private Map<String, Serializable> versionProperties;
public void given() throws Exception public void given() throws Exception
{ {
// add Dublin core aspect
PropertyMap dublinCoreProperties = new PropertyMap(2);
dublinCoreProperties.put(QNAME_PUBLISHER, PUBLISHER);
dublinCoreProperties.put(QNAME_SUBJECT, SUBJECT);
nodeService.addAspect(documentLibrary, ContentModel.ASPECT_DUBLINCORE, dublinCoreProperties);
// setup version properties // setup version properties
versionProperties = new HashMap<String, Serializable>(4); versionProperties = new HashMap<String, Serializable>(4);
versionProperties.put(Version.PROP_DESCRIPTION, DESCRIPTION); versionProperties.put(Version.PROP_DESCRIPTION, DESCRIPTION);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR); versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
versionProperties.put(RecordableVersionServiceImpl.KEY_RECORDABLE_VERSION, true); versionProperties.put(RecordableVersionServiceImpl.KEY_RECORDABLE_VERSION, true);
versionProperties.put(RecordableVersionServiceImpl.KEY_FILE_PLAN, filePlan); versionProperties.put(RecordableVersionServiceImpl.KEY_FILE_PLAN, filePlan);
} }
public void when() public void when()
{ {
// create version // create version
version = versionService.createVersion(dmDocument, versionProperties); versionService.createVersion(dmDocument, versionProperties);
} }
public void then() public void then()
{ {
// version has been created // check that the record has been recorded
assertNotNull(version); checkRecordedVersion(dmDocument, DESCRIPTION, "0.1");
}
});
}
/**
* Adhoc recordable version with recordable set as false
*/
public void testRecordableVersionFalseNoPolicy()
{
doBehaviourDrivenTest(new BehaviourDrivenTest(dmCollaborator)
{
private Map<String, Serializable> versionProperties;
public void given() throws Exception
{
// setup version properties
versionProperties = new HashMap<String, Serializable>(4);
versionProperties.put(Version.PROP_DESCRIPTION, DESCRIPTION);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
versionProperties.put(RecordableVersionServiceImpl.KEY_RECORDABLE_VERSION, false);
versionProperties.put(RecordableVersionServiceImpl.KEY_FILE_PLAN, filePlan);
}
public void when()
{
// create version
versionService.createVersion(dmDocument, versionProperties);
}
public void then()
{
// check that the record has been recorded
checkNotRecordedAspect(dmDocument, DESCRIPTION, "0.1");
}
});
}
/**
* Test no file plan specified (and no default available)
*/
public void testNoFilePlan()
{
doBehaviourDrivenTest(new BehaviourDrivenTest(AlfrescoRuntimeException.class, dmCollaborator)
{
private Map<String, Serializable> versionProperties;
public void given() throws Exception
{
// setup version properties
versionProperties = new HashMap<String, Serializable>(4);
versionProperties.put(Version.PROP_DESCRIPTION, DESCRIPTION);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
versionProperties.put(RecordableVersionServiceImpl.KEY_RECORDABLE_VERSION, true);
}
public void when()
{
// create version
versionService.createVersion(dmDocument, versionProperties);
}
});
}
/**
* Test recorded version with record metadata aspect (want to ensure additional non-rm URI properties and aspects
* don't find their way into the frozen state)
*/
public void testRecordedVersionWithRecordMetadataAspect()
{
doBehaviourDrivenTest(new BehaviourDrivenTest(dmCollaborator)
{
private Map<String, Serializable> versionProperties;
public void given() throws Exception
{
// setup version properties
versionProperties = new HashMap<String, Serializable>(4);
versionProperties.put(Version.PROP_DESCRIPTION, DESCRIPTION);
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
versionProperties.put(RecordableVersionServiceImpl.KEY_RECORDABLE_VERSION, true);
versionProperties.put(RecordableVersionServiceImpl.KEY_FILE_PLAN, filePlan);
}
public void when()
{
// create version
Version version = versionService.createVersion(dmDocument, versionProperties);
// check the version properties // add custom meta-data to record
assertEquals(DESCRIPTION, version.getDescription());
assertEquals("0.1", version.getVersionLabel());
assertEquals(NAME_DM_DOCUMENT, nodeService.getProperty(dmDocument, ContentModel.PROP_NAME));
NodeRef frozen = version.getFrozenStateNodeRef();
assertEquals(NAME_DM_DOCUMENT, nodeService.getProperty(frozen, ContentModel.PROP_NAME));
// record version node reference is available on version
NodeRef record = (NodeRef)version.getVersionProperties().get("RecordVersion"); NodeRef record = (NodeRef)version.getVersionProperties().get("RecordVersion");
assertNotNull(record); assertNotNull(record);
recordService.addRecordType(record, TestModel.ASPECT_RECORD_METADATA);
// record version is an unfiled record nodeService.setProperty(record, TestModel.PROPERTY_RECORD_METADATA, "Peter Wetherall");
assertTrue(recordService.isRecord(record)); }
assertFalse(recordService.isFiled(record));
public void then()
{
// check that the record has been recorded
checkRecordedVersion(dmDocument, DESCRIPTION, "0.1");
} }
}); });
} }
} }

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2005-2014 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.test.integration.version;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionPolicy;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.util.PropertyMap;
/**
* Auto Recordable Versions Integration Test
*
* @author Roy Wetherall
* @since 2.3
*/
public class AutoRecordableVersions extends RecordableVersionsBaseTest
{
public final static String MY_NEW_CONTENT = "this is some new content that I have changed to trigger auto version";
public void testAutoVersionRecordAllRevisions()
{
doBehaviourDrivenTest(new BehaviourDrivenTest(dmCollaborator)
{
public void given() throws Exception
{
// make the node versionable
PropertyMap versionableProperties = new PropertyMap(1);
versionableProperties.put(ContentModel.PROP_INITIAL_VERSION, false);
nodeService.addAspect(dmDocument, ContentModel.ASPECT_VERSIONABLE, versionableProperties);
// set the recordable version policy
PropertyMap recordableVersionProperties = new PropertyMap(1);
recordableVersionProperties.put(PROP_RECORDABLE_VERSION_POLICY, RecordableVersionPolicy.ALL);
recordableVersionProperties.put(PROP_FILE_PLAN, filePlan);
nodeService.addAspect(dmDocument, RecordableVersionModel.ASPECT_VERSIONABLE, recordableVersionProperties);
}
public void when()
{
// generate new version by updating content
ContentWriter writer = contentService.getWriter(dmDocument, ContentModel.PROP_CONTENT, true);
writer.putContent(MY_NEW_CONTENT);
}
public void then()
{
// check that the record has been recorded
checkRecordedVersion(dmDocument, null, "0.2");
}
});
}
}

View File

@@ -0,0 +1,212 @@
/*
* Copyright (C) 2005-2014 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.test.integration.version;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.PropertyMap;
/**
* @author Roy Wetherall
* @since 2.3
*/
public abstract class RecordableVersionsBaseTest extends BaseRMTestCase implements RecordableVersionModel
{
protected static final QName QNAME_PUBLISHER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "publisher");
protected static final QName QNAME_SUBJECT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "subject");
protected static final String DESCRIPTION = "description";
protected static final String PUBLISHER = "publisher";
protected static final String SUBJECT = "subject";
protected static final String OWNER = "Grace Wetherall";
protected static final String CONTENT =
"Simple + Smart. A smarter way to build, a smarter way to deploy. Its simple because we focus on the end "
+ "user and smart because we support more open standards than any other ECM platform, while delivering all "
+ "the value a traditional platform provides.";
@Override
protected boolean isCollaborationSiteTest()
{
return true;
}
@Override
protected void setupCollaborationSiteTestDataImpl()
{
super.setupCollaborationSiteTestDataImpl();
// add titled aspect
PropertyMap titledProperties = new PropertyMap(2);
titledProperties.put(ContentModel.PROP_TITLE, "document title");
titledProperties.put(ContentModel.PROP_DESCRIPTION, "document description");
nodeService.addAspect(dmDocument, ContentModel.ASPECT_TITLED, titledProperties);
// add ownable aspect
PropertyMap ownableProperties = new PropertyMap(1);
ownableProperties.put(ContentModel.PROP_OWNER, OWNER);
nodeService.addAspect(dmDocument, ContentModel.ASPECT_OWNABLE, ownableProperties);
// add Dublin core aspect
PropertyMap dublinCoreProperties = new PropertyMap(2);
dublinCoreProperties.put(QNAME_PUBLISHER, PUBLISHER);
dublinCoreProperties.put(QNAME_SUBJECT, SUBJECT);
nodeService.addAspect(dmDocument, ContentModel.ASPECT_DUBLINCORE, dublinCoreProperties);
// add content
ContentWriter writer = contentService.getWriter(dmDocument, ContentModel.PROP_CONTENT, true);
writer.setEncoding("UTF-8");
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.putContent(CONTENT);
}
/**
* Helper to check that the current version is recorded
*/
protected void checkRecordedVersion(NodeRef document, String description, String versionLabel)
{
// double check that the document is not a record
assertFalse(recordService.isRecord(document));
// store document state
Map<QName, Serializable> beforeProperties = nodeService.getProperties(document);
Set<QName> beforeAspects = nodeService.getAspects(dmDocument);
// get the current version
Version version = versionService.getCurrentVersion(document);
// version has been created
assertNotNull(version);
// check the version properties
assertEquals(description, version.getDescription());
assertEquals(versionLabel, version.getVersionLabel());
// get the frozen state
NodeRef frozen = version.getFrozenStateNodeRef();
// check the properties
checkProperties(frozen, beforeProperties);
// compare aspects
checkAspects(frozen, beforeAspects);
// record version node reference is available on version
NodeRef record = (NodeRef)version.getVersionProperties().get("RecordVersion");
assertNotNull(record);
// record version is an unfiled record
assertTrue(recordService.isRecord(record));
assertFalse(recordService.isFiled(record));
// check the version history
VersionHistory versionHistory = versionService.getVersionHistory(document);
assertNotNull(versionHistory);
Version headVersion = versionHistory.getHeadVersion();
assertNotNull(headVersion);
}
protected void checkNotRecordedAspect(NodeRef document, String description, String versionLabel)
{
// double check that the document is not a record
assertFalse(recordService.isRecord(document));
// get the current version
Version version = versionService.getCurrentVersion(document);
// version has been created
assertNotNull(version);
// check the version properties
assertEquals(description, version.getDescription());
assertEquals(versionLabel, version.getVersionLabel());
// record version node reference is available on version
NodeRef record = (NodeRef)version.getVersionProperties().get("RecordVersion");
assertNull(record);
// check the version history
VersionHistory versionHistory = versionService.getVersionHistory(document);
assertNotNull(versionHistory);
Version headVersion = versionHistory.getHeadVersion();
assertNotNull(headVersion);
}
/**
* Helper to check the properties of a recorded version
*/
protected void checkProperties(NodeRef frozen, Map<QName, Serializable> beforeProperies)
{
Map<QName, Serializable> frozenProperties = nodeService.getProperties(frozen);
Map<QName, Serializable> cloneFrozenProperties = new HashMap<QName, Serializable>(frozenProperties);
for (Map.Entry<QName, Serializable> entry : beforeProperies.entrySet())
{
if (frozenProperties.containsKey(entry.getKey()))
{
Serializable frozenValue = frozenProperties.get(entry.getKey());
assertEquals("Frozen property " + entry.getKey().getLocalName() + " value is incorrect.", entry.getValue(), frozenValue);
cloneFrozenProperties.remove(entry.getKey());
}
else
{
fail("Property missing from frozen state .. " + entry.getKey());
}
}
// frozen properties should be empty
assertTrue("Properties in frozen state, but not in origional. " + cloneFrozenProperties.keySet(), cloneFrozenProperties.isEmpty());
}
/**
* Helper to check the aspects of a recorded version
*/
protected void checkAspects(NodeRef frozen, Set<QName> beforeAspects)
{
Set<QName> cloneBeforeAspects = new HashSet<QName>(beforeAspects);
// compare origional and frozen aspects
Set<QName> frozenAspects = nodeService.getAspects(frozen);
cloneBeforeAspects.removeAll(frozenAspects);
if (!cloneBeforeAspects.isEmpty())
{
fail("Aspects not present in frozen state. " + cloneBeforeAspects.toString());
}
frozenAspects.removeAll(beforeAspects);
if (!frozenAspects.isEmpty())
{
fail("Aspects in the frozen state, but not in origional. " + frozenAspects.toString());
}
}
}

View File

@@ -31,7 +31,8 @@ import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class) @RunWith(Suite.class)
@SuiteClasses( @SuiteClasses(
{ {
AdHocRecordableVersions.class AdHocRecordableVersions.class,
AutoRecordableVersions.class
}) })
public class VersionTestSuite public class VersionTestSuite
{ {

View File

@@ -823,10 +823,18 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
*/ */
protected abstract class BehaviourDrivenTest protected abstract class BehaviourDrivenTest
{ {
/** run in transaction */
protected boolean runInTransactionTests = true; protected boolean runInTransactionTests = true;
/** run as user */
protected String runAsUser = AuthenticationUtil.getAdminUserName();
/** expected exception */
protected Class<?> expectedException; protected Class<?> expectedException;
/**
* Default constructor
*/
public BehaviourDrivenTest() public BehaviourDrivenTest()
{ {
} }
@@ -835,10 +843,25 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
{ {
this.expectedException = expectedException; this.expectedException = expectedException;
} }
public BehaviourDrivenTest(Class<?> expectedException, String runAsUser)
{
this.expectedException = expectedException;
this.runAsUser = runAsUser;
}
public BehaviourDrivenTest(boolean runInTransactionTests) public BehaviourDrivenTest(String runAsUser)
{
this.runAsUser = runAsUser;
}
public BehaviourDrivenTest(String runAsUser, boolean runInTransactionTests)
{ {
this.runInTransactionTests = runInTransactionTests; this.runInTransactionTests = runInTransactionTests;
if (runAsUser != null)
{
this.runAsUser = runAsUser;
}
} }
public void given() throws Exception { /** empty implementation */ } public void given() throws Exception { /** empty implementation */ }
@@ -862,7 +885,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
{ {
given(); given();
} }
}); }, runAsUser);
} }
else else
{ {
@@ -880,7 +903,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
{ {
when(); when();
} }
}); }, runAsUser);
doTestInTransaction(new VoidTest() doTestInTransaction(new VoidTest()
{ {
@@ -889,7 +912,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
{ {
then(); then();
} }
}); }, runAsUser);
} }
else else
{ {
@@ -906,7 +929,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
{ {
when(); when();
} }
}); }, runAsUser);
} }
} }
finally finally
@@ -920,7 +943,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
{ {
after(); after();
} }
}); }, runAsUser);
} }
else else
{ {

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2005-2014 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.test.util;
import org.alfresco.service.namespace.QName;
/**
* @author Roy Wetherall
* @since 2.3
*/
public interface TestModel
{
public static final String TEST_URI = "http://www.alfresco.org/model/rmtest/1.0";
public static final String TEST_PREFIX = "rmt";
public static final QName ASPECT_RECORD_METADATA = QName.createQName(TEST_URI, "recordMetaData");
public static final QName PROPERTY_RECORD_METADATA = QName.createQName(TEST_URI, "recordMetaDataProperty");
}

View File

@@ -47,7 +47,12 @@
</properties> </properties>
</aspect> </aspect>
<aspect name="rmt:recordMetaData"> <aspect name="rmt:recordMetaData">
<properties>
<property name="rmt:recordMetaDataProperty">
<type>d:text</type>
</property>
</properties>
</aspect> </aspect>
</aspects> </aspects>

View File

@@ -87,9 +87,6 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
{ {
super.before(); super.before();
// mock up run as methods
mockRunAsMethods(filePlanPermissionService);
// initialize node's // initialize node's
unfiledRecordContainer = generateContainerNodeRef(TYPE_UNFILED_RECORD_CONTAINER); unfiledRecordContainer = generateContainerNodeRef(TYPE_UNFILED_RECORD_CONTAINER);
unfiledRecordFolder = generateContainerNodeRef(TYPE_UNFILED_RECORD_FOLDER); unfiledRecordFolder = generateContainerNodeRef(TYPE_UNFILED_RECORD_FOLDER);

View File

@@ -41,10 +41,12 @@ import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService; import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;
import org.alfresco.module.org_alfresco_module_rm.report.ReportService; import org.alfresco.module.org_alfresco_module_rm.report.ReportService;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
import org.alfresco.module.org_alfresco_module_rm.util.AuthenticationUtil;
import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.security.permissions.impl.ExtendedPermissionService;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -114,6 +116,9 @@ public class BaseUnitTest implements RecordsManagementModel, ContentModel
@Mock(name="filePlanRoleService") protected FilePlanRoleService mockedFilePlanRoleService; @Mock(name="filePlanRoleService") protected FilePlanRoleService mockedFilePlanRoleService;
@Mock(name="recordsManagementAuditService") protected RecordsManagementAuditService mockedRecordsManagementAuditService; @Mock(name="recordsManagementAuditService") protected RecordsManagementAuditService mockedRecordsManagementAuditService;
@Mock(name="policyBehaviourFilter") protected BehaviourFilter mockedBehaviourFilter; @Mock(name="policyBehaviourFilter") protected BehaviourFilter mockedBehaviourFilter;
@Mock(name="authenticationUtil") protected AuthenticationUtil mockedAuthenticationUtil;
@Mock(name="extendedPermissionService") protected ExtendedPermissionService mockedExtendedPermissionService;
@Mock(name="extendedSecurityService") protected ExtendedSecurityService mockedExtendedSecurityService;
/** application context mock */ /** application context mock */
@Mock(name="applicationContext") protected ApplicationContext mockedApplicationContext; @Mock(name="applicationContext") protected ApplicationContext mockedApplicationContext;
@@ -146,6 +151,9 @@ public class BaseUnitTest implements RecordsManagementModel, ContentModel
} }
}; };
doAnswer(doInTransactionAnswer).when(mockedRetryingTransactionHelper).doInTransaction(any(RetryingTransactionCallback.class)); doAnswer(doInTransactionAnswer).when(mockedRetryingTransactionHelper).doInTransaction(any(RetryingTransactionCallback.class));
// setup mocked authentication util
setupAuthenticationUtilMock();
// setup file plan // setup file plan
filePlan = generateNodeRef(TYPE_FILE_PLAN); filePlan = generateNodeRef(TYPE_FILE_PLAN);
@@ -173,6 +181,43 @@ public class BaseUnitTest implements RecordsManagementModel, ContentModel
doReturn(Collections.singletonList(record)).when(mockedRecordService).getRecords(recordFolder); doReturn(Collections.singletonList(record)).when(mockedRecordService).getRecords(recordFolder);
} }
/**
* Setup authentication util mock
*/
@SuppressWarnings("unchecked")
private void setupAuthenticationUtilMock()
{
// just do the work
doAnswer(new Answer<Object>()
{
@SuppressWarnings("rawtypes")
@Override
public Object answer(InvocationOnMock invocation) throws Throwable
{
RunAsWork work = (RunAsWork)invocation.getArguments()[0];
return work.doWork();
}
}).when(mockedAuthenticationUtil).runAsSystem(any(RunAsWork.class));
// just do the work
doAnswer(new Answer<Object>()
{
@SuppressWarnings("rawtypes")
@Override
public Object answer(InvocationOnMock invocation) throws Throwable
{
RunAsWork work = (RunAsWork)invocation.getArguments()[0];
return work.doWork();
}
}).when(mockedAuthenticationUtil).runAs(any(RunAsWork.class), anyString());
// assume admin
doReturn("admin").when(mockedAuthenticationUtil).getAdminUserName();
doReturn("admin").when(mockedAuthenticationUtil).getFullyAuthenticatedUser();
}
/** /**
* Helper method to generate a qname. * Helper method to generate a qname.
* *
@@ -349,40 +394,6 @@ public class BaseUnitTest implements RecordsManagementModel, ContentModel
doReturn(assocs).when(mockedNodeService).getChildAssocs(parent, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); doReturn(assocs).when(mockedNodeService).getChildAssocs(parent, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
} }
/**
* Helper method to mock up calls to 'run as' methods
* on base service implementation.
*
* @param service
*/
@SuppressWarnings("unchecked")
protected void mockRunAsMethods(ServiceBaseImpl service)
{
doAnswer(new Answer<Object>()
{
@SuppressWarnings("rawtypes")
@Override
public Object answer(InvocationOnMock invocation) throws Throwable
{
RunAsWork work = (RunAsWork)invocation.getArguments()[0];
return work.doWork();
}
}).when(service).runAsSystem(any(RunAsWork.class));
doAnswer(new Answer<Object>()
{
@SuppressWarnings("rawtypes")
@Override
public Object answer(InvocationOnMock invocation) throws Throwable
{
RunAsWork work = (RunAsWork)invocation.getArguments()[0];
return work.doWork();
}
}).when(service).runAs(any(RunAsWork.class), anyString());
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected <T> List<T> buildList(T ... values) protected <T> List<T> buildList(T ... values)
{ {