diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml
index 0c2cddd8ee..e70406b839 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml
@@ -759,6 +759,7 @@
+
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java
index f8174a1059..e7d091eea5 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java
@@ -211,8 +211,11 @@ public class CreateRecordAction extends AuditableActionExecuterAbstractBase
hideRecord = hideRecordValue.booleanValue();
}
- // create record from existing document
- recordService.createRecord(filePlan, actionedUponNodeRef, !hideRecord);
+ synchronized (this)
+ {
+ // create record from existing document
+ recordService.createRecord(filePlan, actionedUponNodeRef, !hideRecord);
+ }
}
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java
index 55fb6adf81..1c1325b416 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java
@@ -11,16 +11,18 @@ import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.action.ParameterDefinitionImpl;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileNotFoundException;
-import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.util.StringUtils;
/**
@@ -33,6 +35,9 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
{
private static Log logger = LogFactory.getLog(CopyMoveLinkFileToBaseAction.class);
+ /** Retrying transaction helper */
+ private RetryingTransactionHelper retryingTransactionHelper;
+
/** action parameters */
public static final String PARAM_DESTINATION_RECORD_FOLDER = "destinationRecordFolder";
public static final String PARAM_PATH = "path";
@@ -89,6 +94,14 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
this.filePlanService = filePlanService;
}
+ /**
+ * @param retryingTransactionHelper retrying transaction helper
+ */
+ public void setRetryingTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
+ {
+ this.retryingTransactionHelper = retryingTransactionHelper;
+ }
+
/**
* @see org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase#addParameterDefinitions(java.util.List)
*/
@@ -103,7 +116,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
- protected void executeImpl(final Action action, final NodeRef actionedUponNodeRef)
+ protected synchronized void executeImpl(final Action action, final NodeRef actionedUponNodeRef)
{
String actionName = action.getActionDefinitionName();
if (isOkToProceedWithAction(actionedUponNodeRef, actionName))
@@ -125,8 +138,25 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER);
if (recordFolder == null)
{
- // get the reference to the record folder based on the relative path
- recordFolder = createOrResolvePath(action, actionedUponNodeRef, targetIsUnfiledRecords);
+ final boolean finaltargetIsUnfiledRecords = targetIsUnfiledRecords;
+ recordFolder = retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback()
+ {
+ public NodeRef execute() throws Throwable
+ {
+ NodeRef result = null;
+ try
+ {
+ // get the reference to the record folder based on the relative path
+ result = createOrResolvePath(action, actionedUponNodeRef, finaltargetIsUnfiledRecords);
+ }
+ catch (DuplicateChildNodeNameException ex)
+ {
+ throw new ConcurrencyFailureException("Cannot create or resolve path.", ex);
+ }
+
+ return result;
+ }
+ }, false, true);
}
// now we have the reference to the target folder we can do some final checks to see if the action is valid
@@ -140,18 +170,22 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
{
try
{
- if(getMode() == CopyMoveLinkFileToActionMode.MOVE)
- {
- fileFolderService.move(actionedUponNodeRef, finalRecordFolder, null);
- }
- else if(getMode() == CopyMoveLinkFileToActionMode.COPY)
- {
- fileFolderService.copy(actionedUponNodeRef, finalRecordFolder, null);
- }
- else if(getMode() == CopyMoveLinkFileToActionMode.LINK)
- {
- recordService.link(actionedUponNodeRef, finalRecordFolder);
- }
+ synchronized (this)
+ {
+ if(getMode() == CopyMoveLinkFileToActionMode.MOVE)
+ {
+ fileFolderService.move(actionedUponNodeRef, finalRecordFolder, null);
+ }
+ else if(getMode() == CopyMoveLinkFileToActionMode.COPY)
+ {
+ fileFolderService.copy(actionedUponNodeRef, finalRecordFolder, null);
+ }
+ else if(getMode() == CopyMoveLinkFileToActionMode.LINK)
+ {
+ recordService.link(actionedUponNodeRef, finalRecordFolder);
+ }
+ }
+
}
catch (FileNotFoundException fileNotFound)
{
@@ -333,18 +367,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
*/
private NodeRef getChild(NodeRef parent, String childName)
{
- NodeRef child = null;
- List children = nodeService.getChildAssocs(parent);
- for (ChildAssociationRef childAssoc : children) {
- NodeRef childNodeRef = childAssoc.getChildRef();
- String existingChildName = (String)nodeService.getProperty(childNodeRef, ContentModel.PROP_NAME);
- if(existingChildName.equals(childName))
- {
- child = childNodeRef;
- break;
- }
- }
- return child;
+ return nodeService.getChildByName(parent, ContentModel.ASSOC_CONTAINS, childName);
}
/**
@@ -364,22 +387,31 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
@Override
public NodeRef doWork()
{
- NodeRef child = null;
- if(targetisUnfiledRecords)
+ // double check that the child hasn't been created by another thread
+ NodeRef child = getChild(parent, childName);
+ if (child == null)
{
- child = fileFolderService.create(parent, childName, RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER).getNodeRef();
- }
- else if(lastAsFolder)
- {
- child = recordFolderService.createRecordFolder(parent, childName);
- }
- else
- {
- if(RecordsManagementModel.TYPE_RECORD_FOLDER.equals(nodeService.getType(parent)))
- {
- throw new AlfrescoRuntimeException("Unable to execute " + action.getActionDefinitionName() + " action, because the destination path could not be created.");
- }
- child = filePlanService.createRecordCategory(parent, childName);
+ if(targetisUnfiledRecords)
+ {
+ // create unfiled folder
+ child = fileFolderService.create(parent, childName, RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER).getNodeRef();
+ }
+ else if(lastAsFolder)
+ {
+ // create record folder
+ child = recordFolderService.createRecordFolder(parent, childName);
+ }
+ else
+ {
+ // ensure we are not trying to create a record categtory in a record folder
+ if(RecordsManagementModel.TYPE_RECORD_FOLDER.equals(nodeService.getType(parent)))
+ {
+ throw new AlfrescoRuntimeException("Unable to execute " + action.getActionDefinitionName() + " action, because the destination path has a record category within a record folder.");
+ }
+
+ // create record category
+ child = filePlanService.createRecordCategory(parent, childName);
+ }
}
return child;
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJob.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJob.java
index 4f20ee4986..77bfa96e95 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJob.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJob.java
@@ -25,6 +25,8 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
@@ -39,6 +41,8 @@ import org.quartz.JobExecutionException;
*/
public class RecordsManagementJob implements Job
{
+ private static Log logger = LogFactory.getLog(RecordsManagementJob.class);
+
private static final long DEFAULT_TIME = 30000L;
private JobLockService jobLockService;
@@ -108,7 +112,18 @@ public class RecordsManagementJob implements Job
}
finally
{
- jobLockService.releaseLock(lockToken, getLockQName());
+ try
+ {
+ jobLockService.releaseLock(lockToken, getLockQName());
+ }
+ catch (LockAcquisitionException e)
+ {
+ // Ignore
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Lock release failed: " + getLockQName() + ": " + lockToken + "(" + e.getMessage() + ")");
+ }
+ }
}
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java
index 82b94f8fd0..d75a5969d8 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java
@@ -18,6 +18,10 @@
*/
package org.alfresco.module.org_alfresco_module_rm.jscript.app;
+import static org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel.READ_RECORDS;
+import static org.alfresco.repo.security.authentication.AuthenticationUtil.runAsSystem;
+import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
+
import java.util.ArrayList;
import java.util.List;
@@ -305,10 +309,10 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JSONC
rootJSONObject.put("originatingLocationPath", originatingLocationPath.toString());
}
}
-
+
/**
* Helper method to get the display path.
- *
+ *
* @param nodeRef node reference
* @return String display path
*/
@@ -329,9 +333,9 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JSONC
* @return
*/
@SuppressWarnings("unchecked")
- private JSONObject setRmNodeValues(NodeRef nodeRef, boolean useShortQName)
+ private JSONObject setRmNodeValues(final NodeRef nodeRef, final boolean useShortQName)
{
- JSONObject rmNodeValues = new JSONObject();
+ JSONObject rmNodeValues = new JSONObject();
// UI convenience type
rmNodeValues.put("uiType", getUIType(nodeRef));
@@ -341,17 +345,20 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JSONC
rmNodeValues.put("kind", kind.toString());
// File plan node reference
- NodeRef filePlan = filePlanService.getFilePlan(nodeRef);
- rmNodeValues.put("filePlan", filePlan.toString());
-
- // Unfiled container node reference
- NodeRef unfiledRecordContainer = filePlanService.getUnfiledContainer(filePlan);
- if (unfiledRecordContainer != null)
+ NodeRef filePlan = getFilePlan(nodeRef);
+ if (permissionService.hasPermission(filePlan, READ_RECORDS).equals(ALLOWED))
{
- rmNodeValues.put("unfiledRecordContainer", unfiledRecordContainer.toString());
- rmNodeValues.put("properties", propertiesToJSON(unfiledRecordContainer, nodeService.getProperties(unfiledRecordContainer), useShortQName));
- QName type = fileFolderService.getFileInfo(unfiledRecordContainer).getType();
- rmNodeValues.put("type", useShortQName ? type.toPrefixString(namespaceService) : type.toString());
+ rmNodeValues.put("filePlan", filePlan.toString());
+
+ // Unfiled container node reference
+ NodeRef unfiledRecordContainer = filePlanService.getUnfiledContainer(filePlan);
+ if (unfiledRecordContainer != null)
+ {
+ rmNodeValues.put("unfiledRecordContainer", unfiledRecordContainer.toString());
+ rmNodeValues.put("properties", propertiesToJSON(unfiledRecordContainer, nodeService.getProperties(unfiledRecordContainer), useShortQName));
+ QName type = fileFolderService.getFileInfo(unfiledRecordContainer).getType();
+ rmNodeValues.put("type", useShortQName ? type.toPrefixString(namespaceService) : type.toString());
+ }
}
// Set the indicators array
@@ -363,6 +370,23 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JSONC
return rmNodeValues;
}
+ /**
+ * Helper method to get the file plan as a system user for the given node
+ *
+ * @param nodeRef The node reference
+ * @return The file plan where the node is in
+ */
+ private NodeRef getFilePlan(final NodeRef nodeRef)
+ {
+ return runAsSystem(new RunAsWork()
+ {
+ public NodeRef doWork()
+ {
+ return filePlanService.getFilePlan(nodeRef);
+ }
+ });
+ }
+
@SuppressWarnings("unchecked")
private void setIndicators(JSONObject rmNodeValues, NodeRef nodeRef)
{
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/ExtendedSecurityAspect.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/ExtendedSecurityAspect.java
index 3ed8750cd2..a35d5cdd82 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/ExtendedSecurityAspect.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/ExtendedSecurityAspect.java
@@ -18,22 +18,14 @@
*/
package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect;
-import java.util.Set;
-
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
import org.alfresco.repo.copy.CopyBehaviourCallback;
import org.alfresco.repo.copy.CopyDetails;
import org.alfresco.repo.copy.DoNothingCopyBehaviourCallback;
-import org.alfresco.repo.node.NodeServicePolicies;
-import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
-import org.alfresco.repo.security.authentication.AuthenticationUtil;
-import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
-import org.alfresco.service.cmr.repository.ChildAssociationRef;
-import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
@@ -46,8 +38,7 @@ import org.alfresco.service.namespace.QName;
(
defaultType = "rma:extendedSecurity"
)
-public class ExtendedSecurityAspect extends BaseBehaviourBean
- implements NodeServicePolicies.OnMoveNodePolicy
+public class ExtendedSecurityAspect extends BaseBehaviourBean
{
/** extended security service */
protected ExtendedSecurityService extendedSecurityService;
@@ -74,40 +65,4 @@ public class ExtendedSecurityAspect extends BaseBehaviourBean
{
return new DoNothingCopyBehaviourCallback();
}
-
- /**
- * Update extended security when moving a node.
- *
- * @see org.alfresco.repo.node.NodeServicePolicies.OnMoveNodePolicy#onMoveNode(org.alfresco.service.cmr.repository.ChildAssociationRef, org.alfresco.service.cmr.repository.ChildAssociationRef)
- */
- @Override
- @Behaviour
- (
- kind = BehaviourKind.CLASS,
- notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT
- )
- public void onMoveNode(final ChildAssociationRef origAssoc, final ChildAssociationRef newAssoc)
- {
- AuthenticationUtil.runAsSystem(new RunAsWork()
- {
- @Override
- public Void doWork()
- {
- NodeRef record = newAssoc.getChildRef();
- NodeRef newParent = newAssoc.getParentRef();
- NodeRef oldParent = origAssoc.getParentRef();
-
- Set readers = extendedSecurityService.getExtendedReaders(record);
- Set writers = extendedSecurityService.getExtendedWriters(record);
-
- extendedSecurityService.addExtendedSecurity(newParent, readers, writers);
- extendedSecurityService.removeExtendedSecurity(oldParent, readers, writers);
-
- return null;
- }
- });
- }
-
-
-
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java
index 0cc4cd45f2..724158dde3 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java
@@ -973,7 +973,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
* @see org.alfresco.module.org_alfresco_module_rm.disposableitem.RecordService#isFiled(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
- public boolean isFiled(NodeRef nodeRef)
+ public boolean isFiled(final NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
@@ -981,15 +981,24 @@ public class RecordServiceImpl extends BaseBehaviourBean
if (isRecord(nodeRef))
{
- ChildAssociationRef childAssocRef = nodeService.getPrimaryParent(nodeRef);
- if (childAssocRef != null)
- {
- NodeRef parent = childAssocRef.getParentRef();
- if (parent != null && recordFolderService.isRecordFolder(parent))
- {
- result = true;
- }
- }
+ result = AuthenticationUtil.runAsSystem(new RunAsWork()
+ {
+ public Boolean doWork() throws Exception
+ {
+ boolean result = false;
+ ChildAssociationRef childAssocRef = nodeService.getPrimaryParent(nodeRef);
+ if (childAssocRef != null)
+ {
+ NodeRef parent = childAssocRef.getParentRef();
+ if (parent != null && recordFolderService.isRecordFolder(parent))
+ {
+ result = true;
+ }
+ }
+ return result;
+ }
+ });
+
}
return result;
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/recordfolder/RecordFolderServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/recordfolder/RecordFolderServiceImpl.java
index eb59072ab3..e432769e1b 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/recordfolder/RecordFolderServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/recordfolder/RecordFolderServiceImpl.java
@@ -32,6 +32,8 @@ import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
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.util.ServiceBaseImpl;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService;
@@ -146,7 +148,7 @@ public class RecordFolderServiceImpl extends ServiceBaseImpl
* @see org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService#isRecordFolderClosed(NodeRef)
*/
@Override
- public boolean isRecordFolderClosed(NodeRef nodeRef)
+ public boolean isRecordFolderClosed(final NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
@@ -156,7 +158,13 @@ public class RecordFolderServiceImpl extends ServiceBaseImpl
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_RECORD_FOLDER_EXPECTED));
}
- return ((Boolean) nodeService.getProperty(nodeRef, PROP_IS_CLOSED)).booleanValue();
+ return AuthenticationUtil.runAsSystem(new RunAsWork()
+ {
+ public Boolean doWork() throws Exception
+ {
+ return ((Boolean) nodeService.getProperty(nodeRef, PROP_IS_CLOSED));
+ }
+ });
}
@Override
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java
index 89193d0def..2ef8b753d8 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java
@@ -40,6 +40,7 @@ import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamic
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authority.RMAuthority;
+import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
@@ -835,7 +836,14 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService,
if (!getAllAssignedToRole(filePlan, role).contains(authorityName))
{
String roleAuthority = authorityService.getName(AuthorityType.GROUP, getFullRoleName(role, filePlan));
- authorityService.addAuthority(roleAuthority, authorityName);
+ try
+ {
+ authorityService.addAuthority(roleAuthority, authorityName);
+ }
+ catch (DuplicateChildNodeNameException exception)
+ {
+ // ignore, because the work has already been performed
+ }
}
return null;
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java
index 61268ae7cb..a4fd365b8c 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java
@@ -46,10 +46,6 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
implements ExtendedSecurityService,
RecordsManagementModel
{
- /** Ad hoc properties used for reference counting */
- private static final QName PROP_EXTENDED_READER_ROLE = QName.createQName(RM_URI, "extendedReaderRole");
- private static final QName PROP_EXTENDED_WRITER_ROLE = QName.createQName(RM_URI, "extendedWriterRole");
-
/** File plan service */
private FilePlanService filePlanService;
@@ -72,7 +68,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
this.filePlanRoleService = filePlanRoleService;
}
- /**
+ /**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#hasExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef)
*/
public boolean hasExtendedSecurity(NodeRef nodeRef)
@@ -137,6 +133,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
if (nodeRef != null)
{
addExtendedSecurityImpl(nodeRef, readers, writers, applyToParents);
+
+ // add to the extended security roles
+ addExtendedSecurityRoles(nodeRef, readers, writers);
}
}
@@ -149,37 +148,37 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
* @param applyToParents
*/
@SuppressWarnings("unchecked")
- private void addExtendedSecurityImpl(NodeRef nodeRef, Set readers, Set writers, boolean applyToParents)
+ private void addExtendedSecurityImpl(final NodeRef nodeRef, Set readers, Set writers, boolean applyToParents)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
ParameterCheck.mandatory("applyToParents", applyToParents);
- // add the aspect if missing
- if (!nodeService.hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY))
- {
- nodeService.addAspect(nodeRef, ASPECT_EXTENDED_SECURITY, null);
- }
-
+ // get the properties
+ final Map properties = nodeService.getProperties(nodeRef);
+
// update the readers map
if (readers != null && readers.size() != 0)
{
// get reader map
- Map readersMap = (Map)nodeService.getProperty(nodeRef, PROP_READERS);
+ Map readersMap = (Map)properties.get(PROP_READERS);
// set the readers property (this will in turn apply the aspect if required)
- nodeService.setProperty(nodeRef, PROP_READERS, (Serializable)addToMap(readersMap, readers));
+ properties.put(PROP_READERS, (Serializable)addToMap(readersMap, readers));
}
-
+
// update the writers map
- if (writers != null && writers.size() != 0)
- {
- // get writer map
- Map writersMap = (Map)nodeService.getProperty(nodeRef, PROP_WRITERS);
-
- // set the writers property (this will in turn apply the aspect if required)
- nodeService.setProperty(nodeRef, PROP_WRITERS, (Serializable)addToMap(writersMap, writers));
- }
+ if (writers != null && writers.size() != 0)
+ {
+ // get writer map
+ Map writersMap = (Map)properties.get(PROP_WRITERS);
+
+ // set the writers property (this will in turn apply the aspect if required)
+ properties.put(PROP_WRITERS, (Serializable)addToMap(writersMap, writers));
+ }
+ // set properties
+ nodeService.setProperties(nodeRef, properties);
+
// apply the readers to any renditions of the content
if (isRecord(nodeRef))
{
@@ -189,22 +188,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
NodeRef child = assoc.getChildRef();
addExtendedSecurityImpl(child, readers, writers, false);
}
- }
-
- // add to the extended security roles
- addExtendedSecurityRoles(nodeRef, readers, writers);
-
- if (applyToParents)
- {
- // apply the extended readers up the file plan primary hierarchy
- NodeRef parent = nodeService.getPrimaryParent(nodeRef).getParentRef();
- if (parent != null &&
- filePlanService.isFilePlanComponent(parent))
- {
- addExtendedSecurityImpl(parent, readers, null, applyToParents);
- addExtendedSecurityImpl(parent, writers, null, applyToParents);
- }
- }
+ }
}
/**
@@ -217,37 +201,29 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
{
NodeRef filePlan = filePlanService.getFilePlan(nodeRef);
- addExtendedSecurityRolesImpl(filePlan, readers, PROP_EXTENDED_READER_ROLE, FilePlanRoleService.ROLE_EXTENDED_READERS);
- addExtendedSecurityRolesImpl(filePlan, writers, PROP_EXTENDED_WRITER_ROLE, FilePlanRoleService.ROLE_EXTENDED_WRITERS);
+ addExtendedSecurityRolesImpl(filePlan, readers, FilePlanRoleService.ROLE_EXTENDED_READERS);
+ addExtendedSecurityRolesImpl(filePlan, writers, FilePlanRoleService.ROLE_EXTENDED_WRITERS);
}
/**
+ * Add extended security roles implementation
*
- * @param filePlan
- * @param authorities
- * @param propertyName
- * @param roleName
+ * @param filePlan file plan
+ * @param authorities authorities
+ * @param roleName role name
*/
- @SuppressWarnings("unchecked")
- private void addExtendedSecurityRolesImpl(NodeRef filePlan, Set authorities, QName propertyName, String roleName)
+ private void addExtendedSecurityRolesImpl(NodeRef filePlan, Set authorities, String roleName)
{
if (authorities != null)
{
- // get the reference count
- Map referenceCountMap = (Map)nodeService.getProperty(filePlan, propertyName);
-
for (String authority : authorities)
{
- if ((!authority.equals(PermissionService.ALL_AUTHORITIES) && !authority.equals(PermissionService.OWNER_AUTHORITY)) &&
- (referenceCountMap == null || !referenceCountMap.containsKey(authority)))
+ if ((!authority.equals(PermissionService.ALL_AUTHORITIES) && !authority.equals(PermissionService.OWNER_AUTHORITY)))
{
// add the authority to the role
filePlanRoleService.assignRoleToAuthority(filePlan, roleName, authority);
}
}
-
- // update the reference count
- nodeService.setProperty(filePlan, propertyName, (Serializable)addToMap(referenceCountMap, authorities));
}
}
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/IssueTestSuite.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/IssueTestSuite.java
index 2c11e9689e..8c52e12ea1 100755
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/IssueTestSuite.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/IssueTestSuite.java
@@ -42,7 +42,9 @@ import org.junit.runners.Suite.SuiteClasses;
RM804Test.class,
RM994Test.class,
RM1039Test.class,
- RM1799Test.class
+ RM1799Test.class,
+ //RM2190Test.class,
+ RM2192Test.class
})
public class IssueTestSuite
{
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2072Test.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2072Test.java
new file mode 100644
index 0000000000..37cf0048aa
--- /dev/null
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2072Test.java
@@ -0,0 +1,182 @@
+/*
+ * 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 .
+ */
+package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction;
+import org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction;
+import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
+import org.alfresco.service.cmr.action.Action;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.rule.Rule;
+import org.alfresco.service.cmr.rule.RuleService;
+import org.alfresco.service.cmr.rule.RuleType;
+
+
+/**
+ * System test for RM-2072: Concurrency exceptions and deadlocks on Records Management "File to" rule
+ *
+ * @author Roy Wetherall
+ * @since 2.2.1.1
+ */
+public class RM2072Test extends BaseRMTestCase
+{
+ private static final int NUMBER_OF_BATCHES = 1;
+ private static final int NUMBER_IN_BATCH = 500;
+
+ private RuleService ruleService;
+ private NodeRef ruleFolder;
+
+ @Override
+ protected void initServices()
+ {
+ super.initServices();
+
+ ruleService = (RuleService)applicationContext.getBean("RuleService");
+ }
+
+ @Override
+ protected boolean isCollaborationSiteTest()
+ {
+ return true;
+ }
+
+ @Override
+ protected boolean isRecordTest()
+ {
+ return true;
+ }
+
+ /**
+ * Given that I have auto declare configured
+ * And that I have auto file configured to a path where only the record folder needs to be created
+ * When I add lots of documents in the same transaction
+ * Then the rules should fire
+ * And the documents should be filed in the new record folder
+ */
+ public void testAutoDeclareAutoFileCreateRecordFolderOnly() throws Exception
+ {
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ // create the folder
+ ruleFolder = fileFolderService.create(documentLibrary, "mytestfolder", ContentModel.TYPE_FOLDER).getNodeRef();
+
+ // create record category
+ NodeRef nodeRefA = filePlanService.createRecordCategory(filePlan, "A");
+ NodeRef nodeRefB = filePlanService.createRecordCategory(nodeRefA, "B");
+ filePlanService.createRecordCategory(nodeRefB, "C");
+
+ Action action = actionService.createAction(CreateRecordAction.NAME);
+ action.setParameterValue(CreateRecordAction.PARAM_FILE_PLAN, filePlan);
+
+ Rule rule = new Rule();
+ rule.setRuleType(RuleType.INBOUND);
+ rule.setTitle("my rule");
+ rule.setAction(action);
+ rule.setExecuteAsynchronously(true);
+ ruleService.saveRule(ruleFolder, rule);
+
+ Action fileAction = actionService.createAction(FileToAction.NAME);
+ fileAction.setParameterValue(FileToAction.PARAM_PATH, "/A/B/C/{date.year.long}/{date.month.long}/{date.day.month}");
+ fileAction.setParameterValue(FileToAction.PARAM_CREATE_RECORD_PATH, true);
+
+ Rule fileRule = new Rule();
+ fileRule.setRuleType(RuleType.INBOUND);
+ fileRule.setTitle("my rule");
+ fileRule.setAction(fileAction);
+ fileRule.setExecuteAsynchronously(true);
+ ruleService.saveRule(filePlanService.getUnfiledContainer(filePlan), fileRule);
+
+ return null;
+ }
+
+ @Override
+ public void test(Void result) throws Exception
+ {
+ assertFalse(ruleService.getRules(ruleFolder).isEmpty());
+ }
+ });
+
+ List records = new ArrayList(NUMBER_OF_BATCHES*NUMBER_IN_BATCH);
+
+ for (int i = 0; i < NUMBER_OF_BATCHES; i++)
+ {
+ final int finali = i;
+ records.addAll(doTestInTransaction(new Test>()
+ {
+ @Override
+ public List run() throws Exception
+ {
+ List records = new ArrayList(NUMBER_IN_BATCH);
+ for (int j = 0; j < NUMBER_IN_BATCH; j++)
+ {
+ int count = (finali+1)*(j+1);
+ String name = "content" + count + ".txt";
+ System.out.println(name + " - creating");
+
+ NodeRef record = fileFolderService.create(ruleFolder, name, ContentModel.TYPE_CONTENT).getNodeRef();
+ records.add(record);
+ }
+ return records;
+ }
+ }));
+ }
+
+ try
+ {
+ while(!records.isEmpty())
+ {
+ Thread.sleep(1000);
+
+ final Iterator temp = records.iterator();
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run() throws Exception
+ {
+ while (temp.hasNext())
+ {
+ NodeRef record = temp.next();
+ if (nodeService.hasAspect(record, ASPECT_RECORD) && recordService.isFiled(record))
+ {
+ String name = (String) nodeService.getProperty(record, ContentModel.PROP_NAME);
+ System.out.println(name + " - complete");
+ temp.remove();
+ }
+ }
+
+ return null;
+ }
+ });
+ }
+ }
+ catch (Exception exception)
+ {
+ exception.printStackTrace();
+ throw exception;
+ }
+ }
+}
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2190Test.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2190Test.java
new file mode 100644
index 0000000000..3a298c7bd3
--- /dev/null
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2190Test.java
@@ -0,0 +1,201 @@
+package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
+
+import static java.util.Arrays.asList;
+import static org.alfresco.service.cmr.rule.RuleType.INBOUND;
+import static org.alfresco.util.GUID.generate;
+import static org.springframework.util.StringUtils.tokenizeToStringArray;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction;
+import org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction;
+import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
+import org.alfresco.service.cmr.action.Action;
+import org.alfresco.service.cmr.model.FileInfo;
+import org.alfresco.service.cmr.model.FileNotFoundException;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.rule.Rule;
+import org.alfresco.service.cmr.rule.RuleService;
+
+/**
+ * System test for RM-2190: Concurrency exception when upload document to several folders with rules configured to file records
+ *
+ * @author Tuna Aksoy
+ * @since 2.2.1.1
+ */
+public class RM2190Test extends BaseRMTestCase
+{
+ private static final int NUMBER_OF_BATCHES = 1;
+ private static final int NUMBER_IN_BATCH = 10;
+
+ private static final String PATH = "/111/222/333";
+
+ private RuleService ruleService;
+
+ private NodeRef rootFolder;
+ private NodeRef folder1;
+ private NodeRef folder2;
+
+ @Override
+ protected void initServices()
+ {
+ super.initServices();
+
+ ruleService = (RuleService) applicationContext.getBean("RuleService");
+ }
+
+ @Override
+ protected boolean isCollaborationSiteTest()
+ {
+ return true;
+ }
+
+ @Override
+ protected boolean isRecordTest()
+ {
+ return true;
+ }
+
+ public void testUploadDocumentsSimultaneouslyWithRules()
+ {
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ rootFolder = fileFolderService.create(documentLibrary, generate(), TYPE_FOLDER).getNodeRef();
+
+ Action createAction = actionService.createAction(CreateRecordAction.NAME);
+ createAction.setParameterValue(CreateRecordAction.PARAM_FILE_PLAN, filePlan);
+
+ Rule declareRule = new Rule();
+ declareRule.setRuleType(INBOUND);
+ declareRule.setTitle(generate());
+ declareRule.setAction(createAction);
+ declareRule.setExecuteAsynchronously(true);
+ declareRule.applyToChildren(true);
+ ruleService.saveRule(rootFolder, declareRule);
+
+ folder1 = fileFolderService.create(rootFolder, generate(), TYPE_FOLDER).getNodeRef();
+ folder2 = fileFolderService.create(rootFolder, generate(), TYPE_FOLDER).getNodeRef();
+
+ Action fileAction = actionService.createAction(FileToAction.NAME);
+ fileAction.setParameterValue(FileToAction.PARAM_PATH, PATH);
+ fileAction.setParameterValue(FileToAction.PARAM_CREATE_RECORD_PATH, true);
+
+ Rule fileRule = new Rule();
+ fileRule.setRuleType(INBOUND);
+ fileRule.setTitle(generate());
+ fileRule.setAction(fileAction);
+ fileRule.setExecuteAsynchronously(true);
+ ruleService.saveRule(unfiledContainer, fileRule);
+
+ return null;
+ }
+
+ @Override
+ public void test(Void result) throws Exception
+ {
+ assertFalse(ruleService.getRules(rootFolder).isEmpty());
+ assertFalse(ruleService.getRules(unfiledContainer).isEmpty());
+ }
+ });
+
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run() throws FileNotFoundException, InterruptedException
+ {
+ Thread thread1 = new Thread()
+ {
+ public void run() {
+ List files = addFilesToFolder(folder1);
+ waitForFilesToBeDeclared(files);
+ }
+ };
+
+ Thread thread2 = new Thread()
+ {
+ public void run() {
+ List files = addFilesToFolder(folder2);
+ waitForFilesToBeDeclared(files);
+ }
+ };
+
+ thread1.start();
+ thread2.start();
+
+ thread1.join(300000);
+ thread2.join(300000);
+
+ return null;
+ }
+
+ @Override
+ public void test(Void result) throws Exception
+ {
+ FileInfo category = fileFolderService.resolveNamePath(filePlan, asList(tokenizeToStringArray(PATH, "/", false, true)));
+ assertEquals(NUMBER_IN_BATCH * 2, nodeService.getChildAssocs(category.getNodeRef()).size());
+ }
+ });
+ }
+
+ private List addFilesToFolder(final NodeRef folder)
+ {
+ List records = new ArrayList(NUMBER_OF_BATCHES * NUMBER_IN_BATCH);
+
+ for (int i = 0; i < NUMBER_OF_BATCHES; i++)
+ {
+ final int finali = i;
+ records.addAll(doTestInTransaction(new Test>()
+ {
+ @Override
+ public List run() throws Exception
+ {
+ List files = new ArrayList(NUMBER_IN_BATCH);
+ for (int j = 0; j < NUMBER_IN_BATCH; j++)
+ {
+ int count = (finali+1)*(j+1);
+ String name = folder.getId() + " - content" + count + ".txt";
+ System.out.println(name + " - creating");
+
+ NodeRef file = fileFolderService.create(folder, name, TYPE_CONTENT).getNodeRef();
+ files.add(file);
+ }
+ return files;
+ }
+ }));
+ }
+
+ return records;
+ }
+
+ private void waitForFilesToBeDeclared(List files)
+ {
+ while (!files.isEmpty())
+ {
+ final Iterator temp = files.iterator();
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run() throws Exception
+ {
+ while (temp.hasNext())
+ {
+ NodeRef record = temp.next();
+ if (nodeService.hasAspect(record, ASPECT_RECORD) && recordService.isFiled(record))
+ {
+ String name = (String) nodeService.getProperty(record, PROP_NAME);
+ System.out.println(name + " - complete");
+ temp.remove();
+ }
+ }
+
+ return null;
+ }
+ });
+ }
+ }
+}
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2192Test.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2192Test.java
new file mode 100644
index 0000000000..bf9759c9a0
--- /dev/null
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2192Test.java
@@ -0,0 +1,156 @@
+package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
+
+import static org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService.ROLE_RECORDS_MANAGER;
+import static org.alfresco.repo.site.SiteModel.SITE_MANAGER;
+import static org.alfresco.repo.site.SiteServiceImpl.getSiteContainer;
+import static org.alfresco.service.cmr.rule.RuleType.INBOUND;
+import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
+import static org.alfresco.service.cmr.site.SiteService.DOCUMENT_LIBRARY;
+import static org.alfresco.service.cmr.site.SiteVisibility.PUBLIC;
+import static org.alfresco.util.GUID.generate;
+
+import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction;
+import org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction;
+import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
+import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
+import org.alfresco.repo.jscript.app.JSONConversionComponent;
+import org.alfresco.service.cmr.action.Action;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.rule.Rule;
+import org.alfresco.service.cmr.rule.RuleService;
+
+/**
+ * Integration test for RM-2192
+ *
+ * @author Tuna Aksoy
+ * @since 2.2.1.1
+ */
+public class RM2192Test extends BaseRMTestCase
+{
+ private static final String PATH = "/111/222/333";
+
+ private RuleService ruleService;
+ private JSONConversionComponent converter;
+
+ private NodeRef folder;
+ private String user;
+ private NodeRef documentLibrary2;
+
+ @Override
+ protected void initServices()
+ {
+ super.initServices();
+
+ ruleService = (RuleService) applicationContext.getBean("RuleService");
+ converter = (JSONConversionComponent) applicationContext.getBean("jsonConversionComponent");
+ }
+
+ @Override
+ protected boolean isCollaborationSiteTest()
+ {
+ return true;
+ }
+
+ @Override
+ protected boolean isRecordTest()
+ {
+ return true;
+ }
+
+ @Override
+ protected boolean isUserTest()
+ {
+ return true;
+ }
+
+ @Override
+ protected void setupCollaborationSiteTestDataImpl()
+ {
+ super.setupCollaborationSiteTestDataImpl();
+
+ String collabSiteId2 = generate();
+ siteService.createSite("site-dashboard", collabSiteId2, generate(), generate(), PUBLIC);
+ documentLibrary2 = getSiteContainer(
+ collabSiteId2,
+ DOCUMENT_LIBRARY,
+ true,
+ siteService,
+ transactionService,
+ taggingService);
+
+ assertNotNull("Collaboration site document library component was not successfully created.", documentLibrary2);
+
+ user = generate();
+ createPerson(user);
+
+ siteService.setMembership(collabSiteId2, user, SITE_MANAGER);
+
+ filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_RECORDS_MANAGER, user);
+ }
+
+ public void testAccessToRecordAfterDeclaring()
+ {
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ folder = fileFolderService.create(documentLibrary2, generate(), TYPE_FOLDER).getNodeRef();
+
+ Action createAction = actionService.createAction(CreateRecordAction.NAME);
+ createAction.setParameterValue(CreateRecordAction.PARAM_FILE_PLAN, filePlan);
+
+ Rule declareRule = new Rule();
+ declareRule.setRuleType(INBOUND);
+ declareRule.setTitle(generate());
+ declareRule.setAction(createAction);
+ declareRule.setExecuteAsynchronously(true);
+ declareRule.applyToChildren(true);
+ ruleService.saveRule(folder, declareRule);
+
+ Action fileAction = actionService.createAction(FileToAction.NAME);
+ fileAction.setParameterValue(FileToAction.PARAM_PATH, PATH);
+ fileAction.setParameterValue(FileToAction.PARAM_CREATE_RECORD_PATH, true);
+
+ Rule fileRule = new Rule();
+ fileRule.setRuleType(INBOUND);
+ fileRule.setTitle(generate());
+ fileRule.setAction(fileAction);
+ fileRule.setExecuteAsynchronously(true);
+ ruleService.saveRule(unfiledContainer, fileRule);
+
+ return null;
+ }
+
+ @Override
+ public void test(Void result) throws Exception
+ {
+ assertFalse(ruleService.getRules(folder).isEmpty());
+ assertFalse(ruleService.getRules(unfiledContainer).isEmpty());
+ }
+ });
+
+ doTestInTransaction(new Test()
+ {
+ NodeRef document;
+
+ @Override
+ public Void run()
+ {
+ document = fileFolderService.create(folder, generate(), TYPE_CONTENT).getNodeRef();
+
+ return null;
+ }
+
+ @Override
+ public void test(Void result) throws InterruptedException
+ {
+ Thread.sleep(10000);
+
+ assertEquals(permissionService.hasPermission(document, READ_RECORDS), ALLOWED);
+ assertTrue(recordService.isFiled(document));
+ assertNotNull(converter.toJSON(document, true));
+ }
+ }, user);
+ }
+}
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/FileToActionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/FileToActionTest.java
index f1d3c9d8a9..a00ef18e61 100644
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/FileToActionTest.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/FileToActionTest.java
@@ -29,6 +29,7 @@ import org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction;
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AccessStatus;
@@ -113,9 +114,17 @@ public class FileToActionTest extends BaseRMTestCase
assertTrue(recordService.isRecord(dmDocument));
assertFalse(recordService.isFiled(dmDocument));
- // is the unfiled container the primary parent of the filed record
- NodeRef parent = nodeService.getPrimaryParent(dmDocument).getParentRef();
- assertEquals(filePlanService.getUnfiledContainer(filePlan), parent);
+ AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork()
+ {
+ public Void doWork() throws Exception
+ {
+ // is the unfiled container the primary parent of the filed record
+ NodeRef parent = nodeService.getPrimaryParent(dmDocument).getParentRef();
+ assertEquals(filePlanService.getUnfiledContainer(filePlan), parent);
+
+ // TODO Auto-generated method stub
+ return null;
+ }});
return null;
}
@@ -203,12 +212,17 @@ public class FileToActionTest extends BaseRMTestCase
private void createRecord(final String path, final String name, final String resolvedPath)
{
+ final String[] pathValues = StringUtils.tokenizeToStringArray(resolvedPath, "/");
+
+ // set parameters
+ Map params = new HashMap(1);
+ params.put(FileToAction.PARAM_PATH, path);
+ params.put(FileToAction.PARAM_CREATE_RECORD_PATH, true);
+
doTestInTransaction(new Test()
{
public Void run() throws Exception
{
- String[] pathValues = StringUtils.tokenizeToStringArray(resolvedPath, "/");
-
// show the folder doesn't exist to begin with
FileInfo createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList(Arrays.asList(pathValues)), false);
assertNull(createdRecordFolder);
@@ -218,11 +232,19 @@ public class FileToActionTest extends BaseRMTestCase
params.put(FileToAction.PARAM_PATH, path);
params.put(FileToAction.PARAM_CREATE_RECORD_PATH, true);
- // execute file-to action
- rmActionService.executeRecordsManagementAction(dmDocument, FileToAction.NAME, params);
+ return null;
+ }
+ }, ADMIN_USER);
+ // execute file-to action
+ rmActionService.executeRecordsManagementAction(dmDocument, FileToAction.NAME, params);
+
+ doTestInTransaction(new Test()
+ {
+ public Void run() throws Exception
+ {
// show the folder has now been created
- createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList(Arrays.asList(pathValues)), false);
+ FileInfo createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList(Arrays.asList(pathValues)), false);
assertNotNull(createdRecordFolder);
assertEquals(name, createdRecordFolder.getName());
NodeRef createdRecordFolderNodeRef = createdRecordFolder.getNodeRef();
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/ExtendedSecurityServiceImplTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/ExtendedSecurityServiceImplTest.java
index 324b0ce759..faeadd3554 100644
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/ExtendedSecurityServiceImplTest.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/ExtendedSecurityServiceImplTest.java
@@ -105,9 +105,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
testMap.put(monkey, Integer.valueOf(1));
testMap.put(elephant, Integer.valueOf(1));
- checkExtendedReaders(filePlan, testMap);
- checkExtendedReaders(rmContainer, testMap);
- checkExtendedReaders(rmFolder, testMap);
checkExtendedReaders(record, testMap);
Set extendedReadersToo = new HashSet(2);
@@ -125,9 +122,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
testMapThree.put(elephant, Integer.valueOf(1));
testMapThree.put(snake, Integer.valueOf(1));
- checkExtendedReaders(filePlan, testMapThree);
- checkExtendedReaders(rmContainer, testMapThree);
- checkExtendedReaders(rmFolder, testMapThree);
checkExtendedReaders(recordToo, testMapToo);
// test remove (with no parent inheritance)
@@ -142,9 +136,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
testMapFour.put(monkey, Integer.valueOf(1));
testMapFour.put(snake, Integer.valueOf(1));
- checkExtendedReaders(filePlan, testMapThree);
- checkExtendedReaders(rmContainer, testMapThree);
- checkExtendedReaders(rmFolder, testMapFour);
checkExtendedReaders(recordToo, testMapToo);
// test remove (apply to parents)
@@ -158,9 +149,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
testMapFour.remove(snake);
testMapToo.remove(snake);
- checkExtendedReaders(filePlan, testMapThree);
- checkExtendedReaders(rmContainer, testMapThree);
- checkExtendedReaders(rmFolder, testMapFour);
checkExtendedReaders(recordToo, testMapToo);
return null;
@@ -197,9 +185,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
extendedSecurityService.addExtendedSecurity(record, extendedReaders, null);
- checkExtendedReaders(filePlan, testMap);
- checkExtendedReaders(rmContainer, testMap);
- checkExtendedReaders(rmFolder, testMap);
checkExtendedReaders(record, testMap);
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordCategory));
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordFolder));
@@ -212,11 +197,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
@Override
public void test(Void result) throws Exception
{
- checkExtendedReaders(filePlan, testMap);
- assertFalse(extendedSecurityService.hasExtendedSecurity(rmContainer));
- // assertEquals(0, extendedSecurityService.getExtendedReaders(rmFolder).size());
- checkExtendedReaders(moveRecordCategory, testMap);
- checkExtendedReaders(moveRecordFolder, testMap);
checkExtendedReaders(record, testMap);
}
});
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordServiceImplTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordServiceImplTest.java
index aac8a820f7..1cf86bb235 100644
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordServiceImplTest.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordServiceImplTest.java
@@ -28,7 +28,6 @@ import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
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.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.role.Role;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
@@ -38,7 +37,6 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.GUID;
@@ -304,15 +302,12 @@ public class RecordServiceImplTest extends BaseRMTestCase
public void test(Void result)
{
- checkPermissions(READ_RECORDS, AccessStatus.ALLOWED, // file
- // plan
- AccessStatus.ALLOWED, // unfiled container
+ checkPermissions(READ_RECORDS, AccessStatus.DENIED, // file plan
+ AccessStatus.DENIED, // unfiled container
AccessStatus.DENIED, // record category
AccessStatus.DENIED, // record folder
AccessStatus.ALLOWED); // doc/record
- permissionReport();
-
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(filePlan,
RMPermissionModel.VIEW_RECORDS));
@@ -362,9 +357,8 @@ public class RecordServiceImplTest extends BaseRMTestCase
@Override
public Void run()
{
- checkPermissions(READ_RECORDS, AccessStatus.ALLOWED, // file
- // plan
- AccessStatus.ALLOWED, // unfiled container
+ checkPermissions(READ_RECORDS, AccessStatus.DENIED, // file plan
+ AccessStatus.DENIED, // unfiled container
AccessStatus.DENIED, // record category
AccessStatus.DENIED, // record folder
AccessStatus.ALLOWED); // doc/record
@@ -394,38 +388,6 @@ public class RecordServiceImplTest extends BaseRMTestCase
}, dmConsumer);
}
- private void permissionReport()
- {
- Set writers = extendedSecurityService.getExtendedWriters(dmDocument);
- for (String writer : writers)
- {
- System.out.println("writer: " + writer);
- }
-
- System.out.println("Users assigned to extended writers role:");
- Set assignedUsers = filePlanRoleService.getUsersAssignedToRole(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS);
- for (String assignedUser : assignedUsers)
- {
- System.out.println(" ... " + assignedUser);
- }
-
- Set perms = permissionService.getAllSetPermissions(filePlan);
- for (AccessPermission perm : perms)
- {
- if (perm.getPermission().contains(RMPermissionModel.EDIT_NON_RECORD_METADATA))
- {
- System.out.println(" ... " + perm.getAuthority() + " - " + perm.getPermission() + " - " + perm.getAccessStatus().toString());
- }
- }
- for (AccessPermission perm : perms)
- {
- if (perm.getPermission().contains(RMPermissionModel.VIEW_RECORDS))
- {
- System.out.println(" ... " + perm.getAuthority() + " - " + perm.getPermission() + " - " + perm.getAccessStatus().toString());
- }
- }
- }
-
public void testCreateRecordNoLink() throws Exception
{
// show that users without WRITE can not create a record from a document