diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-fileplan-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-fileplan-context.xml
index 95ad0bf90e..898b546ea9 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-fileplan-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-fileplan-context.xml
@@ -12,13 +12,13 @@
-
+
+
-
@@ -62,5 +62,21 @@
+
+
+
+
+
+
+ UNFILED_RECORD_CONTAINER
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml
index 0c76022945..8fa9c83db3 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml
@@ -88,6 +88,11 @@
rma:recordsManagementRoot
+
+
+
+ Unfiled Record Container
+ rma:recordsManagementContainer
@@ -618,6 +623,19 @@
true
+
+
+ Unfiled Records
+
+ true
+ false
+
+
+ rma:unfiledRecordContainer
+ true
+ true
+
+
@@ -708,7 +726,6 @@
Date Filed
d:date
- true
@@ -824,6 +841,16 @@
rma:filePlanComponent
+
+
+
+
+
+
+
+ d:any
+
+
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
index 1bc9237751..eb95219e78 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
@@ -67,6 +67,7 @@
org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.isFilePlanComponent=RM.Read.0
org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.getFilePlanComponentKind=ACL_NODE.0.sys:base.ReadProperties, RM.Read.0
org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.getFilePlanComponentKindFromType=RM_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.isRecordsManagementContainer=RM.Read.0
org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.isFilePlan=RM.Read.0
org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.isRecordCategory=RM.Read.0
org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.isRecordFolder=RM.Read.0
@@ -89,9 +90,9 @@
org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.isRecordFolderClosed=RM.Read.0
org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.createRecordFolder=RM.Write.0
org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.getRecords=RM.Read.0,AFTER_RM.FilterNode
+ org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.getRecordFolders=RM.Read.0,AFTER_RM.FilterNode
org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.getRecordMetaDataAspects=RM_ALLOW
- org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.getRecordFolders=RM.Read.0,AFTER_RM.FilterNode
- org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.isRecordDeclared=RM.Read.0
+ org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.isRecordDeclared=RM.Read.0
org.alfresco.module.org_alfresco_module_rm.RecordsManagementService.*=RM_DENY
]]>
@@ -480,7 +481,13 @@
org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.createRole=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.updateRole=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.deleteRole=RM_ALLOW
- org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.assignRoleToAuthority=RM_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.assignRoleToAuthority=RM_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.hasExtendedReaders=RM_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.getExtendedReaders=RM_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.setExtendedReaders=RM_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.removeExtendedReaders=RM_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.removeAllExtendedReaders=RM_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.*=RM_DENY
]]>
@@ -787,6 +794,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.alfresco.module.org_alfresco_module_rm.record.RecordService
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${server.transaction.mode.default}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
list of record meta-data aspects
- */
- Set getRecordMetaDataAspects();
-
/**
* Get all the record folders that a record is filed into.
*
@@ -463,12 +463,27 @@ public interface RecordsManagementService
*/
// TODO rename to List getParentRecordFolders(NodeRef record);
List getRecordFolders(NodeRef record);
-
+
+ /********** Deprecated **********/
+
+ /**
+ * Get a list of all the record meta-data aspects
+ *
+ * @return {@link Set}<{@link QName}> list of record meta-data aspects
+ *
+ * @deprecated As of 2.1, replaced by {@link RecordService#getRecordMetaDataAspects()}
+ */
+ @Deprecated
+ Set getRecordMetaDataAspects();
+
/**
* Indicates whether the record is declared
- *
+ *
* @param nodeRef node reference (record)
* @return boolean true if record is declared, false otherwise
+ *
+ * @deprecated As of 2.1, replaced by {@link RecordsService#isDeclared()}
*/
- boolean isRecordDeclared(NodeRef nodeRef);
+ @Deprecated
+ boolean isRecordDeclared(NodeRef nodeRef);
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceImpl.java
index 8a25859fdd..49fa37e409 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceImpl.java
@@ -20,7 +20,6 @@ package org.alfresco.module.org_alfresco_module_rm;
import java.io.Serializable;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@@ -34,11 +33,11 @@ import org.alfresco.model.RenditionModel;
import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementCustomModel;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
-import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -77,7 +76,6 @@ public class RecordsManagementServiceImpl implements RecordsManagementService,
private final static String MSG_PARENT_RECORD_FOLDER_ROOT = "rm.service.parent-record-folder-root";
private final static String MSG_PARENT_RECORD_FOLDER_TYPE = "rm.service.parent-record-folder-type";
private final static String MSG_RECORD_FOLDER_TYPE = "rm.service.record-folder-type";
- private final static String MSG_NOT_RECORD = "rm.service.not-record";
/** Store that the RM roots are contained within */
@SuppressWarnings("unused")
@@ -105,9 +103,6 @@ public class RecordsManagementServiceImpl implements RecordsManagementService,
/** Well-known location of the scripts folder. */
private NodeRef scriptsFolderNodeRef = new NodeRef("workspace", "SpacesStore", "rm_scripts");
- /** List of available record meta-data aspects */
- private Set recordMetaDataAspects;
-
/** Java behaviour */
private JavaBehaviour onChangeToDispositionActionDefinition;
@@ -253,7 +248,7 @@ public class RecordsManagementServiceImpl implements RecordsManagementService,
throw new AlfrescoRuntimeException("Unable to complete operation, because only content can be filed within a record folder.");
}
}
- }
+ }
/**
* On add content to container
@@ -290,7 +285,17 @@ public class RecordsManagementServiceImpl implements RecordsManagementService,
NodeRef thumbnail = childAssocRef.getChildRef();
if (nodeService.exists(thumbnail) == true)
{
+ // apply file plan component aspect to thumbnail
nodeService.addAspect(thumbnail, ASPECT_FILE_PLAN_COMPONENT, null);
+
+ // manage any extended readers
+ RecordsManagementSecurityService securityService = serviceRegistry.getRecordsManagementSecurityService();
+ NodeRef parent = childAssocRef.getParentRef();
+ Set readers = securityService.getExtendedReaders(parent);
+ if (readers != null && readers.size() != 0)
+ {
+ securityService.setExtendedReaders(thumbnail, readers, false);
+ }
}
}
@@ -442,6 +447,15 @@ public class RecordsManagementServiceImpl implements RecordsManagementService,
return instanceOf(nodeRef, TYPE_FILE_PLAN);
}
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementService#isRecordsManagementContainer(org.alfresco.service.cmr.repository.NodeRef)
+ */
+ @Override
+ public boolean isRecordsManagementContainer(NodeRef nodeRef)
+ {
+ return instanceOf(nodeRef, TYPE_RECORDS_MANAGEMENT_CONTAINER);
+ }
+
/**
* Utility method to safely and quickly determine if a node is a type (or sub-type) of the one specified.
*/
@@ -512,6 +526,10 @@ public class RecordsManagementServiceImpl implements RecordsManagementService,
{
result = FilePlanComponentKind.DISPOSITION_SCHEDULE;
}
+ else if (instanceOf(nodeRef, TYPE_UNFILED_RECORD_CONTAINER) == true)
+ {
+ result = FilePlanComponentKind.UNFILED_RECORD_CONTAINER;
+ }
}
return result;
@@ -1001,7 +1019,7 @@ public class RecordsManagementServiceImpl implements RecordsManagementService,
List records = getRecords(recordFolder);
for (NodeRef record : records)
{
- if (isRecordDeclared(record) == false)
+ if (serviceRegistry.getRecordService().isDeclared(record) == false)
{
result = false;
break;
@@ -1120,31 +1138,6 @@ public class RecordsManagementServiceImpl implements RecordsManagementService,
return createRecordFolder(parent, name, type, null);
}
- /**
- * @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementService#getRecordMetaDataAspects()
- */
- public Set getRecordMetaDataAspects()
- {
- if (recordMetaDataAspects == null)
- {
- recordMetaDataAspects = new HashSet(7);
- Collection aspects = dictionaryService.getAllAspects();
- for (QName aspect : aspects)
- {
- AspectDefinition def = dictionaryService.getAspect(aspect);
- if (def != null)
- {
- QName parent = def.getParentName();
- if (parent != null && ASPECT_RECORD_META_DATA.equals(parent) == true)
- {
- recordMetaDataAspects.add(aspect);
- }
- }
- }
- }
- return recordMetaDataAspects;
- }
-
/**
* @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementService#getRecords(org.alfresco.service.cmr.repository.NodeRef)
*/
@@ -1164,21 +1157,7 @@ public class RecordsManagementServiceImpl implements RecordsManagementService,
}
}
return result;
- }
-
- /**
- * @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementService#isRecord(org.alfresco.service.cmr.repository.NodeRef, boolean)
- */
- public boolean isRecordDeclared(NodeRef record)
- {
- if (isRecord(record) == false)
- {
- throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_NOT_RECORD, record.toString()));
- }
- return (this.nodeService.hasAspect(record, ASPECT_DECLARED_RECORD));
- }
-
-
+ }
/**
* This method examines the old and new property sets and for those properties which
@@ -1271,4 +1250,24 @@ public class RecordsManagementServiceImpl implements RecordsManagementService,
return result;
}
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementService#getRecordMetaDataAspects()
+ */
+ @Override
+ @Deprecated
+ public Set getRecordMetaDataAspects()
+ {
+ return serviceRegistry.getRecordService().getRecordMetaDataAspects();
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementService#isRecordDeclared(org.alfresco.service.cmr.repository.NodeRef)
+ */
+ @Override
+ @Deprecated
+ public boolean isRecordDeclared(NodeRef nodeRef)
+ {
+ return serviceRegistry.getRecordService().isDeclared(nodeRef);
+ }
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceRegistry.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceRegistry.java
index ae6ba63928..551d1d406c 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceRegistry.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceRegistry.java
@@ -23,6 +23,7 @@ import org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditSe
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
import org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService;
+import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService;
import org.alfresco.service.NotAuditable;
import org.alfresco.service.ServiceRegistry;
@@ -45,6 +46,7 @@ public interface RecordsManagementServiceRegistry extends ServiceRegistry
static final QName RECORDS_MANAGEMENT_SECURITY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "RecordsManagementSecurityService");
static final QName RECORDS_MANAGEMENT_AUDIT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "RecordsManagementAuditService");
static final QName CAPABILITY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CapabilityService");
+ static final QName RECORD_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "RecordService");
/**
* @return records management service
@@ -52,6 +54,12 @@ public interface RecordsManagementServiceRegistry extends ServiceRegistry
@NotAuditable
RecordsManagementService getRecordsManagementService();
+ /**
+ * @return record service
+ */
+ @NotAuditable
+ RecordService getRecordService();
+
/**
* @return disposition service
*/
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceRegistryImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceRegistryImpl.java
index b27d6c86fc..d340b0190f 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceRegistryImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceRegistryImpl.java
@@ -23,6 +23,7 @@ import org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditSe
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
import org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService;
+import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService;
import org.alfresco.repo.service.ServiceDescriptorRegistry;
@@ -65,6 +66,14 @@ public class RecordsManagementServiceRegistryImpl extends ServiceDescriptorRegis
{
return (RecordsManagementService)getService(RECORDS_MANAGEMENT_SERVICE);
}
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry#getRecordService()
+ */
+ public RecordService getRecordService()
+ {
+ return (RecordService)getService(RECORD_SERVICE);
+ }
/**
* @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry#getRecordsManagementSecurityService()
@@ -74,7 +83,7 @@ public class RecordsManagementServiceRegistryImpl extends ServiceDescriptorRegis
return (RecordsManagementSecurityService)getService(RECORDS_MANAGEMENT_SECURITY_SERVICE);
}
- /*
+ /**
* @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry#getRecordsManagementAuditService()
*/
public RecordsManagementAuditService getRecordsManagementAuditService()
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java
index b7cad234b4..e8e3111ea2 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java
@@ -57,6 +57,9 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel
// Records management root container
public static final QName TYPE_FILE_PLAN = QName.createQName(RM_URI, "filePlan");
+ // Unfiled record container
+ public static final QName TYPE_UNFILED_RECORD_CONTAINER = QName.createQName(RM_URI, "unfiledRecordContainer");
+
// Disposition instructions aspect
public static final QName ASPECT_SCHEDULED = QName.createQName(RM_URI, "scheduled");
public static final QName ASSOC_DISPOSITION_SCHEDULE = QName.createQName(RM_URI, "dispositionSchedule");
@@ -167,6 +170,7 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel
public static final QName ASPECT_RECORDS_MANAGEMENT_ROOT = QName.createQName(RM_URI, "recordsManagementRoot");
public static final QName ASSOC_HOLDS = QName.createQName(RM_URI, "holds");
public static final QName ASSOC_TRANSFERS = QName.createQName(RM_URI, "transfers");
+ public static final QName ASSOC_UNFILED_RECORDS = QName.createQName(RM_URI, "unfiledRecords");
// Hold type
public static final QName TYPE_HOLD = QName.createQName(RM_URI, "hold");
@@ -223,4 +227,8 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel
// Loaded Data Set Ids
public static final QName ASPECT_LOADED_DATA_SET_ID = QName.createQName(RM_URI, "loadedDataSetId");
public static final QName PROP_LOADED_DATA_SET_IDS = QName.createQName(RM_URI, "loadedDataSetIds");
+
+ // Extended readers aspect
+ public static final QName ASPECT_EXTENDED_READERS = QName.createQName(RM_URI, "extendedReaders");
+ public static final QName PROP_READERS = QName.createQName(RM_URI, "readers");
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java
new file mode 100644
index 0000000000..037dd56ae9
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2005-2012 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.record;
+
+import java.util.Set;
+
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * Record Service Interface.
+ *
+ * @author Roy Wetherall
+ * @since 2.1
+ */
+public interface RecordService
+{
+ /**
+ * Get a list of all the record meta-data aspects
+ *
+ * @return {@link Set}<{@link QName}> list of record meta-data aspects
+ */
+ Set getRecordMetaDataAspects();
+
+ /**
+ * Indicates whether the record is declared
+ *
+ * @param nodeRef node reference (record)
+ * @return boolean true if record is declared, false otherwise
+ */
+ boolean isDeclared(NodeRef nodeRef);
+
+ /**
+ * Create a new record from an existing document.
+ *
+ * @param filePlan
+ * @param document
+ */
+ void createRecordFromDocument(NodeRef filePlan, NodeRef document);
+
+ // TODO boolean isRecordFiled(NodeRef record);
+ // TODO boolean isRecordClassified(NodeRef record);
+
+ // NodeRef getNewRecordContainer(NodeRef filePlan);
+
+ //NodeRef createRecord(NodeRef filePlan, NodeRef document);
+
+ // TODO NodeRef createAndFileRecord(NodeRef recordFolder, NodeRef document);
+
+ // TODO void fileRecord(NodeRef recordFolder, NodeRef record);
+
+ public NodeRef getUnfiledRecordContainer(NodeRef filePlan);
+}
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
new file mode 100644
index 0000000000..dc53ecf1c9
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2005-2012 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.record;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService;
+import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService;
+import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService;
+import org.alfresco.repo.policy.PolicyComponent;
+import org.alfresco.service.cmr.dictionary.AspectDefinition;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.security.PermissionService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.service.namespace.RegexQNamePattern;
+
+/**
+ * Record service implementation
+ *
+ * @author Roy Wetherall
+ * @since 2.1
+ */
+public class RecordServiceImpl implements RecordService, RecordsManagementModel
+{
+ /** Node service **/
+ private NodeService nodeService;
+
+ /** Indentiy service */
+ private IdentifierService identifierService;
+
+ /** Records management service */
+ private RecordsManagementService recordsManagementService;
+
+ /** Dictionary service */
+ private DictionaryService dictionaryService;
+
+ /** Policy component */
+ private PolicyComponent policyComponent;
+
+ /** Permission service */
+ private PermissionService permissionService;
+
+ /** Records management security service */
+ private RecordsManagementSecurityService recordsManagementSecurityService;
+
+ /** List of available record meta-data aspects */
+ private Set recordMetaDataAspects;
+
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ public void setIdentifierService(IdentifierService identifierService)
+ {
+ this.identifierService = identifierService;
+ }
+
+ public void setRecordsManagementService(RecordsManagementService recordsManagementService)
+ {
+ this.recordsManagementService = recordsManagementService;
+ }
+
+ public void setDictionaryService(DictionaryService dictionaryService)
+ {
+ this.dictionaryService = dictionaryService;
+ }
+
+ public void setPolicyComponent(PolicyComponent policyComponent)
+ {
+ this.policyComponent = policyComponent;
+ }
+
+ public void setPermissionService(PermissionService permissionService)
+ {
+ this.permissionService = permissionService;
+ }
+
+ public void setRecordsManagementSecurityService(RecordsManagementSecurityService recordsManagementSecurityService)
+ {
+ this.recordsManagementSecurityService = recordsManagementSecurityService;
+ }
+
+ public void init()
+ {
+ // policyComponent.bindAssociationBehaviour(
+ // QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateChildAssociation"),
+ // TYPE_UNFILED_RECORD_CONTAINER,
+ // ContentModel.ASSOC_CONTAINS,
+ // new JavaBehaviour(this, "onCreateNewRecord", NotificationFrequency.TRANSACTION_COMMIT));
+ }
+
+// public void onCreateNewRecord(final ChildAssociationRef childAssocRef, boolean bNew)
+// {
+// AuthenticationUtil.runAsSystem(new RunAsWork()
+// {
+// @Override
+// public Void doWork() throws Exception
+// {
+// NodeRef nodeRef = childAssocRef.getChildRef();
+// if (nodeService.exists(nodeRef) == true)
+// {
+// QName type = nodeService.getType(nodeRef);
+// if (ContentModel.TYPE_CONTENT.equals(type) == true ||
+// dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) == true)
+// {
+// makeRecord(nodeRef);
+// }
+// else
+// {
+// throw new AlfrescoRuntimeException("Only content can be created as a record.");
+// }
+// }
+//
+// return null;
+// }
+// });
+// }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#getRecordMetaDataAspects()
+ */
+ public Set getRecordMetaDataAspects()
+ {
+ if (recordMetaDataAspects == null)
+ {
+ recordMetaDataAspects = new HashSet(7);
+ Collection aspects = dictionaryService.getAllAspects();
+ for (QName aspect : aspects)
+ {
+ AspectDefinition def = dictionaryService.getAspect(aspect);
+ if (def != null)
+ {
+ QName parent = def.getParentName();
+ if (parent != null && ASPECT_RECORD_META_DATA.equals(parent) == true)
+ {
+ recordMetaDataAspects.add(aspect);
+ }
+ }
+ }
+ }
+ return recordMetaDataAspects;
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#isDeclared(org.alfresco.service.cmr.repository.NodeRef)
+ */
+ public boolean isDeclared(NodeRef record)
+ {
+ return (nodeService.hasAspect(record, ASPECT_DECLARED_RECORD));
+ }
+
+ @Override
+ public void createRecordFromDocument(NodeRef filePlan, NodeRef document)
+ {
+ // skip everything if the document is already a record
+ if (nodeService.hasAspect(document, ASPECT_RECORD) == false)
+ {
+ // get the documents readers
+ Long aclId = nodeService.getNodeAclId(document);
+ Set readers = permissionService.getReaders(aclId);
+
+ // get the documents primary parent assoc
+ ChildAssociationRef parentAssoc = nodeService.getPrimaryParent(document);
+
+ /// get the new record container for the file plan
+ NodeRef newRecordContainer = getUnfiledRecordContainer(filePlan);
+ if (newRecordContainer == null)
+ {
+ throw new AlfrescoRuntimeException("Unable to create record, because new record container could not be found.");
+ }
+
+ // move the document into the file plan
+ nodeService.moveNode(document, newRecordContainer, ContentModel.ASSOC_CONTAINS, parentAssoc.getQName());
+
+ // maintain the original primary location
+ nodeService.addChild(parentAssoc.getParentRef(), document, parentAssoc.getTypeQName(), parentAssoc.getQName());
+
+ // make the document a record
+ makeRecord(document);
+
+ // set the readers
+ recordsManagementSecurityService.setExtendedReaders(document, readers);
+ }
+ }
+
+ /**
+ *
+ * @param document
+ */
+ private void makeRecord(NodeRef document)
+ {
+ nodeService.addAspect(document, RecordsManagementModel.ASPECT_RECORD, null);
+
+ String recordId = identifierService.generateIdentifier(ASPECT_RECORD, nodeService.getPrimaryParent(document).getParentRef());
+ nodeService.setProperty(document, PROP_IDENTIFIER, recordId);
+ }
+
+ /**
+ *
+ * @param filePlan
+ * @return
+ */
+ public NodeRef getUnfiledRecordContainer(NodeRef filePlan)
+ {
+ List assocs = nodeService.getChildAssocs(filePlan, ASSOC_UNFILED_RECORDS, RegexQNamePattern.MATCH_ALL);
+ if (assocs.size() != 1)
+ {
+ throw new AlfrescoRuntimeException("Error getting the unfiled container, because the container cannot be indentified.");
+ }
+ return assocs.get(0).getChildRef();
+ }
+
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/admin/RmRolesGet.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/admin/RmRolesGet.java
index 71f004e46b..1255120eb3 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/admin/RmRolesGet.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/admin/RmRolesGet.java
@@ -19,6 +19,7 @@
package org.alfresco.module.org_alfresco_module_rm.script.admin;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -65,19 +66,26 @@ public class RmRolesGet extends DeclarativeWebScript
// TODO should be passed
List roots = rmService.getFilePlans();
- NodeRef root = roots.get(0);
-
- // Get the user filter
- String user = req.getParameter("user");
- if (user != null && user.length() != 0)
+ if (roots != null && roots.size() > 0)
{
- roles = rmSecurityService.getRolesByUser(root, user);
+ NodeRef root = roots.get(0);
+
+ // Get the user filter
+ String user = req.getParameter("user");
+ if (user != null && user.length() != 0)
+ {
+ roles = rmSecurityService.getRolesByUser(root, user);
+ }
+ else
+ {
+ roles = rmSecurityService.getRoles(root);
+ }
}
else
{
- roles = rmSecurityService.getRoles(root);
+ roles = new HashSet(1);
}
-
+
model.put("roles", roles);
return model;
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedReaderDynamicAuthority.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedReaderDynamicAuthority.java
new file mode 100644
index 0000000000..8eaf471512
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedReaderDynamicAuthority.java
@@ -0,0 +1,173 @@
+/*
+` * Copyright (C) 2005-2012 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.security;
+
+import java.util.Set;
+
+import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.repo.security.permissions.DynamicAuthority;
+import org.alfresco.repo.security.permissions.PermissionReference;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.security.AuthorityService;
+import org.alfresco.service.cmr.security.AuthorityType;
+import org.alfresco.service.namespace.QName;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ * Extended readers dynamic authority implementation.
+ *
+ * @author Roy Wetherall
+ * @since 2.1
+ */
+public class ExtendedReaderDynamicAuthority implements DynamicAuthority,
+ RecordsManagementModel,
+ ApplicationContextAware
+{
+ /** Extended reader role */
+ public static final String EXTENDED_READER = "ROLE_EXTENDED_READER";
+
+ /** Authority service */
+ private AuthorityService authorityService;
+
+ /** Records management security service */
+ private RecordsManagementSecurityService recordsManagementSecurityService;
+
+ /** Node service */
+ private NodeService nodeService;
+
+ /** Application context */
+ private ApplicationContext applicationContext;
+
+ // NOTE: we get the services directly from the application context in this way to avoid
+ // cyclic relationships and issues when loading the application context
+
+ /**
+ * @return authority service
+ */
+ private AuthorityService getAuthorityService()
+ {
+ if (authorityService == null)
+ {
+ authorityService = (AuthorityService)applicationContext.getBean("authorityService");
+ }
+ return authorityService;
+ }
+
+ /**
+ * @return records management security service
+ */
+ public RecordsManagementSecurityService getRecordsManagementSecurityService()
+ {
+ if (recordsManagementSecurityService == null)
+ {
+ recordsManagementSecurityService = (RecordsManagementSecurityService)applicationContext.getBean("recordsManagementSecurityService");
+ }
+ return recordsManagementSecurityService;
+ }
+
+ /**
+ * @return node service
+ */
+ public NodeService getNodeService()
+ {
+ if (nodeService == null)
+ {
+ nodeService = (NodeService)applicationContext.getBean("nodeService");
+ }
+ return nodeService;
+ }
+
+ /**
+ * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
+ */
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
+ {
+ this.applicationContext = applicationContext;
+ }
+
+ /**
+ * @see org.alfresco.repo.security.permissions.DynamicAuthority#getAuthority()
+ */
+ @Override
+ public String getAuthority()
+ {
+ return EXTENDED_READER;
+ }
+
+ /**
+ * @see org.alfresco.repo.security.permissions.DynamicAuthority#hasAuthority(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
+ */
+ @Override
+ public boolean hasAuthority(NodeRef nodeRef, String userName)
+ {
+ boolean result = false;
+
+ if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_READERS) == true)
+ {
+ Set readers = getRecordsManagementSecurityService().getExtendedReaders(nodeRef);
+ if (readers != null)
+ {
+ for (String reader : readers)
+ {
+ if ("GROUP_EVERYONE".equals(reader) == true)
+ {
+ // 'eveyone' has read
+ result = true;
+ break;
+ }
+ else if (reader.startsWith("GROUP_") == true)
+ {
+ // check group to see if the user is contained
+ Set contained = getAuthorityService().getContainedAuthorities(AuthorityType.USER, reader, false);
+ if (contained.isEmpty() == false &&
+ contained.contains(userName) == true)
+ {
+ result = true;
+ break;
+ }
+ }
+ else
+ {
+ // presume we have a user
+ if (reader.equals(userName) == true)
+ {
+ result = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
+ */
+ @Override
+ public Set requiredFor()
+ {
+ return null;
+ }
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityService.java
index 7cb8b18895..3eba852122 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityService.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityService.java
@@ -152,4 +152,56 @@ public interface RecordsManagementSecurityService
* @param permission permission
*/
void deletePermission(NodeRef nodeRef, String authority, String permission);
+
+ /**
+ * Indicates whether the node has any extended readers set or not.
+ *
+ * @param nodeRef node reference
+ * @return boolean true if the node has extended readers set, false otherwise
+ * @since 2.1
+ */
+ boolean hasExtendedReaders(NodeRef nodeRef);
+
+ /**
+ * Gets the set authorities that are extended readers for the given node.
+ *
+ * @param nodeRef node reference
+ * @return {@link Set}<{@link String}> extended readers
+ * @since 2.1
+ */
+ Set getExtendedReaders(NodeRef nodeRef);
+
+ /**
+ * Set the authorities that are extended readers on the node. Applies extended readers to
+ * file plan parent hierarchy.
+ *
+ * @param nodeRef node reference
+ * @param readers extended readers
+ * @since 2.1
+ */
+ void setExtendedReaders(NodeRef nodeRef, Set readers);
+
+ /**
+ *
+ * @param nodeRef
+ * @param readers
+ * @param applyToParents
+ * @since 2.1
+ */
+ void setExtendedReaders(NodeRef nodeRef, Set readers, boolean applyToParents);
+
+ /**
+ *
+ * @param nodeRef
+ * @param readers
+ * @since 2.1
+ */
+ void removeExtendedReaders(NodeRef nodeRef, Set readers);
+
+ /**
+ *
+ * @param nodeRef
+ * @since 2.1
+ */
+ void removeAllExtendedReaders(NodeRef nodeRef);
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java
index 9ae1855e1e..a397570951 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java
@@ -22,12 +22,16 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.Serializable;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
+import org.alfresco.model.RenditionModel;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService;
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
@@ -39,6 +43,7 @@ import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
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.cmr.repository.NodeService;
@@ -56,6 +61,9 @@ import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
/**
* Records management permission service implementation
@@ -63,7 +71,9 @@ import org.json.JSONObject;
* @author Roy Wetherall
*/
public class RecordsManagementSecurityServiceImpl implements RecordsManagementSecurityService,
- RecordsManagementModel
+ RecordsManagementModel,
+ ApplicationContextAware,
+ NodeServicePolicies.OnMoveNodePolicy
{
/** Capability service */
@@ -90,9 +100,24 @@ public class RecordsManagementSecurityServiceImpl implements RecordsManagementSe
/** Records management role zone */
public static final String RM_ROLE_ZONE_PREFIX = "rmRoleZone";
+ /** Unfiled record container name */
+ private static final String NAME_UNFILED_CONTAINER = "Unfiled Records";
+
/** Logger */
private static Log logger = LogFactory.getLog(RecordsManagementSecurityServiceImpl.class);
+ /** Application context */
+ private ApplicationContext applicationContext;
+
+ /**
+ * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
+ */
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
+ {
+ this.applicationContext = applicationContext;
+ }
+
/**
* Set the capability service
*
@@ -183,7 +208,12 @@ public class RecordsManagementSecurityServiceImpl implements RecordsManagementSe
policyComponent.bindClassBehaviour(
NodeServicePolicies.OnCreateNodePolicy.QNAME,
TYPE_RECORD_FOLDER,
- new JavaBehaviour(this, "onCreateRecordFolder", NotificationFrequency.TRANSACTION_COMMIT));
+ new JavaBehaviour(this, "onCreateRecordFolder", NotificationFrequency.TRANSACTION_COMMIT));
+
+ policyComponent.bindClassBehaviour(
+ NodeServicePolicies.OnMoveNodePolicy.QNAME,
+ ASPECT_RECORD,
+ new JavaBehaviour(this, "onMoveNode", NotificationFrequency.TRANSACTION_COMMIT));
}
/**
@@ -204,9 +234,9 @@ public class RecordsManagementSecurityServiceImpl implements RecordsManagementSe
if (nodeService.exists(rmRootNode) == true)
{
- AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork