From 186b88c44cf9bfe49008631f201d16054c2449fd Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Thu, 5 Dec 2013 03:53:52 +0000 Subject: [PATCH] RM-1098: Refactor RM behaviours * added BehaviourRegister interface and provided access to behaviour objects when named git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@58608 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../rm-disposition-properties-context.xml | 2 +- .../rm-model-context.xml | 1 + .../rm-service-context.xml | 1 + .../property/DispositionProperty.java | 160 ++++++++---------- .../model/BaseBehaviourBean.java | 34 +++- .../model/rma/aspect/RecordAspect.java | 78 ++++++++- .../record/RecordServiceImpl.java | 115 ++++--------- .../AnnotatedBehaviourPostProcessor.java | 29 +++- .../repo/policy/annotation/Behaviour.java | 3 + .../policy/annotation/BehaviourRegistry.java | 46 +++++ 10 files changed, 278 insertions(+), 191 deletions(-) create mode 100755 rm-server/source/java/org/alfresco/repo/policy/annotation/BehaviourRegistry.java diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-disposition-properties-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-disposition-properties-context.xml index 68c93efcc0..c16bd5567d 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-disposition-properties-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-disposition-properties-context.xml @@ -11,8 +11,8 @@ - + diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml index 8121e7d2a9..12dc76e9fd 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml @@ -100,6 +100,7 @@ + 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 9bdc0c35b3..e15c2f3aa2 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 @@ -1196,6 +1196,7 @@ + diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/property/DispositionProperty.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/property/DispositionProperty.java index 3d33c3ebc3..949202ad3c 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/property/DispositionProperty.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/property/DispositionProperty.java @@ -1,5 +1,20 @@ -/** - * +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . */ package org.alfresco.module.org_alfresco_module_rm.disposition.property; @@ -12,48 +27,38 @@ import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionAction; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean; import org.alfresco.repo.node.NodeServicePolicies; -import org.alfresco.repo.policy.JavaBehaviour; -import org.alfresco.repo.policy.PolicyComponent; 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.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.Period; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; /** + * Disposition property implementation bean. + * * @author Roy Wetherall */ -public class DispositionProperty implements NodeServicePolicies.OnUpdatePropertiesPolicy, - RecordsManagementModel +@BehaviourBean +public class DispositionProperty extends BaseBehaviourBean + implements NodeServicePolicies.OnUpdatePropertiesPolicy { /** Property QName */ private QName propertyName; - /** Behaviour */ - private JavaBehaviour behaviour; - /** Namespace service */ private NamespaceService namespaceService; /** Disposition service */ private DispositionService dispositionService; - /** Policy component */ - private PolicyComponent policyComponent; - - /** Dictionary service */ - private DictionaryService dictionaryService; - - /** Node service */ - private NodeService nodeService; - /** Indicates whether this disposition property applies to a folder level disposition */ private boolean appliesToFolderLevel = true; @@ -79,30 +84,6 @@ public class DispositionProperty implements NodeServicePolicies.OnUpdateProperti this.dispositionService = dispositionService; } - /** - * @param policyComponent policy component - */ - public void setPolicyComponent(PolicyComponent policyComponent) - { - this.policyComponent = policyComponent; - } - - /** - * @param dictionaryService dictionary service - */ - public void setDictionaryService(DictionaryService dictionaryService) - { - this.dictionaryService = dictionaryService; - } - - /** - * @param nodeService node service - */ - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - /** * @param propertyName property name (as string) */ @@ -157,14 +138,7 @@ public class DispositionProperty implements NodeServicePolicies.OnUpdateProperti public void init() { // register with disposition service - dispositionService.registerDispositionProperty(this); - - // register interest in the update properties policy for disposition - behaviour = new JavaBehaviour(this, "onUpdateProperties", NotificationFrequency.TRANSACTION_COMMIT); - policyComponent.bindClassBehaviour( - NodeServicePolicies.OnUpdatePropertiesPolicy.QNAME, - ASPECT_DISPOSITION_LIFECYCLE, - behaviour); + dispositionService.registerDispositionProperty(this); } /** @@ -201,6 +175,12 @@ public class DispositionProperty implements NodeServicePolicies.OnUpdateProperti * @see org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy#onUpdateProperties(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, java.util.Map) */ @Override + @Behaviour + ( + kind = BehaviourKind.CLASS, + type = "rma:dispositionLifecycle", + notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT + ) public void onUpdateProperties( final NodeRef nodeRef, final Map before, @@ -210,57 +190,49 @@ public class DispositionProperty implements NodeServicePolicies.OnUpdateProperti { // has the property we care about changed? if (isPropertyUpdated(before, after) == true) - { - behaviour.disable(); - try - { - AuthenticationUtil.runAs(new RunAsWork() + { + AuthenticationUtil.runAs(new RunAsWork() + { + @Override + public Void doWork() throws Exception { - @Override - public Void doWork() throws Exception - { - Date updatedDateValue = (Date)after.get(propertyName); - if (updatedDateValue != null) - { - DispositionAction dispositionAction = dispositionService.getNextDispositionAction(nodeRef); - if (dispositionAction != null) + Date updatedDateValue = (Date)after.get(propertyName); + if (updatedDateValue != null) + { + DispositionAction dispositionAction = dispositionService.getNextDispositionAction(nodeRef); + if (dispositionAction != null) + { + DispositionActionDefinition daDefinition = dispositionAction.getDispositionActionDefinition(); + if (daDefinition != null) { - DispositionActionDefinition daDefinition = dispositionAction.getDispositionActionDefinition(); - if (daDefinition != null) + // check whether the next disposition action matches this disposition property + if (propertyName.equals(daDefinition.getPeriodProperty()) == true) { - // check whether the next disposition action matches this disposition property - if (propertyName.equals(daDefinition.getPeriodProperty()) == true) - { - Period period = daDefinition.getPeriod(); - Date updatedAsOf = period.getNextDate(updatedDateValue); - - // update asOf date on the disposition action based on the new property value - NodeRef daNodeRef = dispositionAction.getNodeRef(); - nodeService.setProperty(daNodeRef, PROP_DISPOSITION_AS_OF, updatedAsOf); - } + Period period = daDefinition.getPeriod(); + Date updatedAsOf = period.getNextDate(updatedDateValue); + + // update asOf date on the disposition action based on the new property value + NodeRef daNodeRef = dispositionAction.getNodeRef(); + nodeService.setProperty(daNodeRef, PROP_DISPOSITION_AS_OF, updatedAsOf); } } } - else + } + else + { + // throw an exception if the property is being 'cleared' + if (before.get(propertyName) != null) { - // throw an exception if the property is being 'cleared' - if (before.get(propertyName) != null) - { - throw new AlfrescoRuntimeException( - "Error updating property " + propertyName.toPrefixString(namespaceService) + - " to null, because property is being used to determine a disposition date."); - } + throw new AlfrescoRuntimeException( + "Error updating property " + propertyName.toPrefixString(namespaceService) + + " to null, because property is being used to determine a disposition date."); } - - return null; } - }, AuthenticationUtil.getSystemUserName()); - } - finally - { - behaviour.enable(); - } + return null; + } + + }, AuthenticationUtil.getSystemUserName()); } } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/BaseBehaviourBean.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/BaseBehaviourBean.java index b9f84b3442..ff3cd01dd1 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/BaseBehaviourBean.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/BaseBehaviourBean.java @@ -3,7 +3,12 @@ */ package org.alfresco.module.org_alfresco_module_rm.model; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.repo.policy.BehaviourFilter; +import org.alfresco.repo.policy.annotation.BehaviourRegistry; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; @@ -18,7 +23,8 @@ import org.apache.commons.logging.LogFactory; * @author Roy Wetherall * @since 2.2 */ -public abstract class BaseBehaviourBean implements RecordsManagementModel +public abstract class BaseBehaviourBean implements RecordsManagementModel, + BehaviourRegistry { /** Logger */ protected static Log logger = LogFactory.getLog(BaseBehaviourBean.class); @@ -32,6 +38,9 @@ public abstract class BaseBehaviourBean implements RecordsManagementModel /** behaviour filter */ protected BehaviourFilter behaviourFilter; + /** behaviour map */ + protected Map behaviours = new HashMap(7); + /** * @param nodeService node service */ @@ -76,4 +85,27 @@ public abstract class BaseBehaviourBean implements RecordsManagementModel return result; } + /** + * @see org.alfresco.repo.policy.annotation.BehaviourRegistry#registerBehaviour(java.lang.String, org.alfresco.repo.policy.Behaviour) + */ + @Override + public void registerBehaviour(String name, org.alfresco.repo.policy.Behaviour behaviour) + { + if (behaviours.containsKey(name) == true) + { + throw new AlfrescoRuntimeException("Can not register behaviour, because name " + name + "has already been used."); + } + + behaviours.put(name, behaviour); + } + + /** + * @see org.alfresco.repo.policy.annotation.BehaviourRegistry#getBehaviour(java.lang.String) + */ + @Override + public org.alfresco.repo.policy.Behaviour getBehaviour(String name) + { + return behaviours.get(name); + } + } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java index 7e258a26af..5ca6a27d1f 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java @@ -19,6 +19,7 @@ package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect; import java.io.Serializable; +import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -28,6 +29,8 @@ import org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies; import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementCustomModel; import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RecordsManagementSearchBehaviour; +import org.alfresco.module.org_alfresco_module_rm.model.security.ModelAccessDeniedException; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; import org.alfresco.repo.copy.CopyBehaviourCallback; import org.alfresco.repo.copy.CopyDetails; @@ -43,6 +46,7 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.ScriptService; import org.alfresco.service.namespace.QName; +import org.alfresco.util.EqualsHelper; /** * rma:record behaviour bean @@ -58,7 +62,8 @@ public class RecordAspect extends BaseBehaviourBean implements NodeServicePolicies.OnCreateChildAssociationPolicy, RecordsManagementPolicies.OnCreateReference, RecordsManagementPolicies.OnRemoveReference, - NodeServicePolicies.OnMoveNodePolicy + NodeServicePolicies.OnMoveNodePolicy, + NodeServicePolicies.OnUpdatePropertiesPolicy { /** Well-known location of the scripts folder. */ // TODO make configurable @@ -70,6 +75,9 @@ public class RecordAspect extends BaseBehaviourBean /** script service */ protected ScriptService scriptService; + /** record service */ + protected RecordService recordService; + /** * @param extendedSecurityService extended security service */ @@ -86,6 +94,14 @@ public class RecordAspect extends BaseBehaviourBean this.scriptService = scriptService; } + /** + * @param recordService record service + */ + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } + /** * Behaviour to ensure renditions have the appropriate extended security. * @@ -236,6 +252,66 @@ public class RecordAspect extends BaseBehaviourBean } } + /** + * Ensure that the user only updates record properties that they have permission to. + * + * @see org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy#onUpdateProperties(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, java.util.Map) + */ + @Override + @Behaviour + ( + name = "onUpdateProperties", + kind = BehaviourKind.CLASS + ) + public void onUpdateProperties(final NodeRef nodeRef, final Map before, final Map after) + { + if (AuthenticationUtil.getFullyAuthenticatedUser() != null && + AuthenticationUtil.isRunAsUserTheSystemUser() == false && + nodeService.exists(nodeRef) == true) + { + if (recordService.isRecord(nodeRef) == true) + { + for (QName property : after.keySet()) + { + Serializable beforeValue = null; + if (before != null) + { + beforeValue = before.get(property); + } + + Serializable afterValue = null; + if (after != null) + { + afterValue = after.get(property); + } + + boolean propertyUnchanged = false; + if (beforeValue != null && afterValue != null && + beforeValue instanceof Date && afterValue instanceof Date) + { + // deal with date values + propertyUnchanged = (((Date)beforeValue).compareTo((Date)afterValue) == 0); + } + else + { + // otherwise + propertyUnchanged = EqualsHelper.nullSafeEquals(beforeValue, afterValue); + } + + if (propertyUnchanged == false && + recordService.isPropertyEditable(nodeRef, property) == false) + { + // the user can't edit the record property + throw new ModelAccessDeniedException( + "The user " + AuthenticationUtil.getFullyAuthenticatedUser() + + " does not have the permission to edit the record property " + property.toString() + + " on the node " + nodeRef.toString()); + } + } + } + } + } + /** * Executes a reference script if present * 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 4ac4504c11..a9cb8fa136 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 @@ -41,7 +41,7 @@ import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService; 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.model.security.ModelAccessDeniedException; +import org.alfresco.module.org_alfresco_module_rm.model.rma.aspect.RecordAspect; import org.alfresco.module.org_alfresco_module_rm.notification.RecordsManagementNotificationHelper; import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService; import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; @@ -52,6 +52,9 @@ import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.policy.Behaviour.NotificationFrequency; import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; +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.repo.security.permissions.AccessDeniedException; @@ -79,7 +82,6 @@ import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; -import org.alfresco.util.EqualsHelper; import org.alfresco.util.ParameterCheck; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; @@ -93,11 +95,11 @@ import org.springframework.extensions.surf.util.I18NUtil; * @author Roy Wetherall * @since 2.1 */ +@BehaviourBean public class RecordServiceImpl implements RecordService, RecordsManagementModel, RecordsManagementCustomModel, NodeServicePolicies.OnCreateChildAssociationPolicy, - NodeServicePolicies.OnUpdatePropertiesPolicy, NodeServicePolicies.OnAddAspectPolicy, NodeServicePolicies.OnRemoveAspectPolicy { @@ -194,6 +196,9 @@ public class RecordServiceImpl implements RecordService, /** Permission service */ private PermissionService permissionService; + + /** Record aspect */ + private RecordAspect recordAspect; /** List of available record meta-data aspects */ private Set recordMetaDataAspects; @@ -203,10 +208,6 @@ public class RecordServiceImpl implements RecordService, this, "onCreateChildAssociation", NotificationFrequency.FIRST_EVENT); - private JavaBehaviour onUpdateProperties = new JavaBehaviour( - this, - "onUpdateProperties", - NotificationFrequency.EVERY_EVENT); private JavaBehaviour onDeleteDeclaredRecordLink = new JavaBehaviour( this, "onDeleteDeclaredRecordLink", @@ -347,6 +348,14 @@ public class RecordServiceImpl implements RecordService, { this.permissionService = permissionService; } + + /** + * @param recordAspect record aspect + */ + public void setRecordAspect(RecordAspect recordAspect) + { + this.recordAspect = recordAspect; + } /** * Init method @@ -358,31 +367,23 @@ public class RecordServiceImpl implements RecordService, TYPE_RECORD_FOLDER, ContentModel.ASSOC_CONTAINS, onCreateChildAssociation); - policyComponent.bindClassBehaviour( - NodeServicePolicies.OnUpdatePropertiesPolicy.QNAME, - ASPECT_RECORD, - onUpdateProperties); + policyComponent.bindAssociationBehaviour( NodeServicePolicies.BeforeDeleteChildAssociationPolicy.QNAME, ContentModel.TYPE_FOLDER, ContentModel.ASSOC_CONTAINS, onDeleteDeclaredRecordLink); - - // Handle the special case when we are dealing with new records that are being added via a file protocol - policyComponent.bindClassBehaviour( - NodeServicePolicies.OnAddAspectPolicy.QNAME, - ContentModel.ASPECT_NO_CONTENT, - new JavaBehaviour(this, "onAddAspect", NotificationFrequency.EVERY_EVENT)); - policyComponent.bindClassBehaviour( - NodeServicePolicies.OnRemoveAspectPolicy.QNAME, - ContentModel.ASPECT_NO_CONTENT, - new JavaBehaviour(this, "onRemoveAspect", NotificationFrequency.EVERY_EVENT)); } /** * @see org.alfresco.repo.node.NodeServicePolicies.OnRemoveAspectPolicy#onRemoveAspect(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName) */ @Override + @Behaviour + ( + kind = BehaviourKind.CLASS, + type = "sys:noContent" + ) public void onRemoveAspect(NodeRef nodeRef, QName aspect) { @@ -411,6 +412,11 @@ public class RecordServiceImpl implements RecordService, * @see org.alfresco.repo.node.NodeServicePolicies.OnAddAspectPolicy#onAddAspect(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName) */ @Override + @Behaviour + ( + kind = BehaviourKind.CLASS, + type = "sys:noContent" + ) public void onAddAspect(NodeRef nodeRef, QName aspect) { switchNames(nodeRef); @@ -509,69 +515,6 @@ public class RecordServiceImpl implements RecordService, }, AuthenticationUtil.getSystemUserName()); } - /** - * Ensure that the user only updates record properties that they have permission to. - * - * @see org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy#onUpdateProperties(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, java.util.Map) - */ - @Override - public void onUpdateProperties(final NodeRef nodeRef, final Map before, final Map after) - { - onUpdateProperties.disable(); - try - { - if (AuthenticationUtil.getFullyAuthenticatedUser() != null && - AuthenticationUtil.isRunAsUserTheSystemUser() == false && - nodeService.exists(nodeRef) == true) - { - if (isRecord(nodeRef) == true) - { - for (QName property : after.keySet()) - { - Serializable beforeValue = null; - if (before != null) - { - beforeValue = before.get(property); - } - - Serializable afterValue = null; - if (after != null) - { - afterValue = after.get(property); - } - - boolean propertyUnchanged = false; - if (beforeValue != null && afterValue != null && - beforeValue instanceof Date && afterValue instanceof Date) - { - // deal with date values - propertyUnchanged = (((Date)beforeValue).compareTo((Date)afterValue) == 0); - } - else - { - // otherwise - propertyUnchanged = EqualsHelper.nullSafeEquals(beforeValue, afterValue); - } - - if (propertyUnchanged == false && - isPropertyEditable(nodeRef, property) == false) - { - // the user can't edit the record property - throw new ModelAccessDeniedException( - "The user " + AuthenticationUtil.getFullyAuthenticatedUser() + - " does not have the permission to edit the record property " + property.toString() + - " on the node " + nodeRef.toString()); - } - } - } - } - } - finally - { - onUpdateProperties.enable(); - } - } - /** * Looking specifically at linked content that was declared a record from a non-rm site. * When the site or the folder that the link was declared in is deleted we need to remove @@ -599,7 +542,7 @@ public class RecordServiceImpl implements RecordService, @Override public void disablePropertyEditableCheck() { - onUpdateProperties.disable(); + recordAspect.getBehaviour("onUpdateProperties").disable(); } /** @@ -608,7 +551,7 @@ public class RecordServiceImpl implements RecordService, @Override public void enablePropertyEditableCheck() { - onUpdateProperties.enable(); + recordAspect.getBehaviour("onUpdateProperties").enable(); } /** diff --git a/rm-server/source/java/org/alfresco/repo/policy/annotation/AnnotatedBehaviourPostProcessor.java b/rm-server/source/java/org/alfresco/repo/policy/annotation/AnnotatedBehaviourPostProcessor.java index 3a11c873e5..02e8d2e6ac 100644 --- a/rm-server/source/java/org/alfresco/repo/policy/annotation/AnnotatedBehaviourPostProcessor.java +++ b/rm-server/source/java/org/alfresco/repo/policy/annotation/AnnotatedBehaviourPostProcessor.java @@ -88,9 +88,10 @@ public class AnnotatedBehaviourPostProcessor implements BeanPostProcessor } /** + * Register behaviours. * - * @param bean - * @param beanName + * @param bean bean + * @param beanName bean name */ private void registerBehaviours(Object bean, String beanName) { @@ -115,11 +116,12 @@ public class AnnotatedBehaviourPostProcessor implements BeanPostProcessor } /** + * Register behaviour. * - * @param behaviourBean - * @param bean - * @param beanName - * @param method + * @param behaviourBean behaviour bean annotation + * @param bean bean + * @param beanName bean name + * @param method method */ private void registerBehaviour(BehaviourBean behaviourBean, Object bean, String beanName, Method method) { @@ -138,13 +140,13 @@ public class AnnotatedBehaviourPostProcessor implements BeanPostProcessor { if (behaviour.isService() == false) { - logger.debug(" ... registering " + behaviour.kind() + " behaviour for " + beanName + "." + method.getName() + + logger.debug(" ... binding " + behaviour.kind() + " behaviour for " + beanName + "." + method.getName() + " for policy " + policy.toString() + " and type " + type.toString()); } else { - logger.debug(" ... registering " + behaviour.kind() + " service behaviour for " + beanName + "." + method.getName() + + logger.debug(" ... binding " + behaviour.kind() + " service behaviour for " + beanName + "." + method.getName() + " for policy " + policy.toString()); } } @@ -152,6 +154,17 @@ public class AnnotatedBehaviourPostProcessor implements BeanPostProcessor // create java behaviour object JavaBehaviour javaBehaviour = new JavaBehaviour(bean, method.getName(), behaviour.notificationFrequency()); + // determine whether we should register the behaviour + if (bean instanceof BehaviourRegistry && behaviour.name().isEmpty() == false) + { + if (logger.isDebugEnabled() == true) + { + logger.debug(" ... adding behaviour to registry with name " + behaviour.name()); + } + + ((BehaviourRegistry)bean).registerBehaviour(behaviour.name(), javaBehaviour); + } + // deal with class behaviours if (BehaviourKind.CLASS.equals(behaviour.kind()) == true) { diff --git a/rm-server/source/java/org/alfresco/repo/policy/annotation/Behaviour.java b/rm-server/source/java/org/alfresco/repo/policy/annotation/Behaviour.java index 7fc6b7ecdc..dc3ce81a67 100644 --- a/rm-server/source/java/org/alfresco/repo/policy/annotation/Behaviour.java +++ b/rm-server/source/java/org/alfresco/repo/policy/annotation/Behaviour.java @@ -34,6 +34,9 @@ import org.alfresco.repo.policy.Behaviour.NotificationFrequency; @Retention(value = RetentionPolicy.RUNTIME) public @interface Behaviour { + /** lookup name of the behaviour, if none specified behaviour is not recorded in the registry */ + String name() default ""; + /** kind of behaviour */ BehaviourKind kind(); diff --git a/rm-server/source/java/org/alfresco/repo/policy/annotation/BehaviourRegistry.java b/rm-server/source/java/org/alfresco/repo/policy/annotation/BehaviourRegistry.java new file mode 100755 index 0000000000..800f0a9ae1 --- /dev/null +++ b/rm-server/source/java/org/alfresco/repo/policy/annotation/BehaviourRegistry.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.policy.annotation; + +import org.alfresco.repo.policy.Behaviour; + + +/** + * Interface for a behaviour registry. + * + * @author Roy Wetherall + * @since 2.2 + */ +public interface BehaviourRegistry +{ + /** + * Register a behaviour against a given name. + * + * @param behaviour behaviour + */ + void registerBehaviour(String name, org.alfresco.repo.policy.Behaviour behaviour); + + /** + * Gets the behaviour for a given name. + * + * @param name behaviour name + * @return {@link Behaviour} behaviour, null otherwise + */ + org.alfresco.repo.policy.Behaviour getBehaviour(String name); +}