mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged DEV to HEAD
31489: Fix MT NodeRef translation in policy filter (ALF-10178) 31452: Sync DEV branch with HEAD 30312: Reintegrated HEAD 30281: Comprehensive DEBUG logging to track behaviour enable/disable states for transactions - Part of ALF-10178: BehaviourFilter fails when nesting disable/enable calls 30280: Fixed importer's use of behaviour filter - The change in the BehaviourFilter contract means that all disable calls must be matched with an equivalent enable call. Enabling globally no longer wipes out vetos put in place by other code. - Part of ALF-10178: BehaviourFilter fails when nesting disable/enable calls 30279: Removed unnecessary behaviour enablement checks is VersionService (ALF-10178) 30278: Fixed behaviour re-enabling for StoreSelectorAspectContentStore (ALF-10178) 30240: Fixed ALF-10178: BehaviourFilter fails when nesting disable/enable calls - Behaviour enable/disable now uses reference counting to check the state of different behaviour levels - Added unit test to test - Re-enabled test for ALF-10177: Test disabled: CheckOutCheckInServiceImplTest.testalfrescoCheckoutDoesntModifyNode but renamed to CheckOutCheckInServiceImplTest.testAlfrescoCheckoutDoesNotModifyNode - Going into DEV branch to run through tests 30236: Branch for fixing BehaviourFilter nesting git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@31619 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -37,11 +37,8 @@ import javax.transaction.UserTransaction;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.filesys.alfresco.AlfrescoContext;
|
||||
import org.alfresco.filesys.alfresco.AlfrescoDiskDriver;
|
||||
import org.alfresco.filesys.alfresco.AlfrescoNetworkFile;
|
||||
import org.alfresco.filesys.config.ServerConfigurationBean;
|
||||
import org.alfresco.filesys.alfresco.AlfrescoTxDiskDriver;
|
||||
import org.alfresco.filesys.alfresco.ShuffleCache;
|
||||
import org.alfresco.jlan.server.SrvSession;
|
||||
import org.alfresco.jlan.server.core.DeviceContext;
|
||||
import org.alfresco.jlan.server.core.DeviceContextException;
|
||||
@@ -4228,7 +4225,7 @@ public class ContentDiskDriver extends AlfrescoTxDiskDriver implements DiskInter
|
||||
|
||||
// copy over the node creator and owner properties
|
||||
// need to disable the auditable aspect first to prevent default audit behaviour
|
||||
boolean alreadyDisabled = policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
try
|
||||
{
|
||||
nodeService.setProperty(toNode, ContentModel.PROP_CREATOR, nodeService.getProperty(fromNode, ContentModel.PROP_CREATOR));
|
||||
@@ -4236,10 +4233,7 @@ public class ContentDiskDriver extends AlfrescoTxDiskDriver implements DiskInter
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(!alreadyDisabled)
|
||||
{
|
||||
policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
}
|
||||
policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
}
|
||||
|
||||
Set<AccessPermission> permissions = permissionService.getAllSetPermissions(fromNode);
|
||||
|
@@ -262,7 +262,7 @@ public class CopiedFromAspectPatch extends AbstractPatch
|
||||
public void process(Pair<Long, NodeRef> entry) throws Throwable
|
||||
{
|
||||
// Disable auditable aspect
|
||||
behaviourFilter.disableAllBehaviours();
|
||||
behaviourFilter.disableBehaviour();
|
||||
// Disable rules
|
||||
ruleService.disableRules();
|
||||
try
|
||||
@@ -272,7 +272,7 @@ public class CopiedFromAspectPatch extends AbstractPatch
|
||||
finally
|
||||
{
|
||||
ruleService.enableRules();
|
||||
behaviourFilter.enableAllBehaviours();
|
||||
behaviourFilter.enableBehaviour();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
|
@@ -20,7 +20,9 @@ package org.alfresco.repo.audit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.policy.BehaviourFilter;
|
||||
@@ -32,7 +34,7 @@ import org.aopalliance.intercept.MethodInvocation;
|
||||
/**
|
||||
* An interceptor that disables and then enables ASPECT_AUDITABLE behaviours
|
||||
* around method calls.
|
||||
*
|
||||
* <ul>
|
||||
* <li>The name of the method must match a supplied list (See
|
||||
* {@link #setMethodNames(List)}).</li>
|
||||
* <li>For this interceptor to disable and enable policy behaviour, the first
|
||||
@@ -42,16 +44,18 @@ import org.aopalliance.intercept.MethodInvocation;
|
||||
* values (See {@link #setArgumentValues(List)}. The second argument must be
|
||||
* a QName. If a list is not supplied the second argument is not checked.</li>
|
||||
* <li>The BehaviourFilter to be enabled or disabled must be set (See
|
||||
* {@link #setBehaviourFilter(BehaviourFilter)}).
|
||||
* {@link #setBehaviourFilter(BehaviourFilter)}).</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Stas Sokolovsky
|
||||
*/
|
||||
public class DisableAuditableBehaviourInterceptor implements MethodInterceptor
|
||||
{
|
||||
private BehaviourFilter behaviourFilter;
|
||||
private List<String> methodNames;
|
||||
private List<String> argumentValues;
|
||||
private Set<String> methodNames = new HashSet<String>(0);
|
||||
private Set<QName> argumentQNameValues = new HashSet<QName>(0);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object invoke(MethodInvocation methodInvocation) throws Throwable
|
||||
{
|
||||
String methodName = methodInvocation.getMethod().getName();
|
||||
@@ -77,7 +81,7 @@ public class DisableAuditableBehaviourInterceptor implements MethodInterceptor
|
||||
|
||||
if (behaviourFilter != null &&
|
||||
methodNames.contains(methodName) &&
|
||||
(arg1 == null || argumentValues.contains(arg1.toString())))
|
||||
(arg1 == null || argumentQNameValues.contains(arg1)))
|
||||
{
|
||||
for (NodeRef nodeRef : nodes)
|
||||
{
|
||||
@@ -108,11 +112,16 @@ public class DisableAuditableBehaviourInterceptor implements MethodInterceptor
|
||||
|
||||
public void setMethodNames(List<String> methodNames)
|
||||
{
|
||||
this.methodNames = methodNames;
|
||||
this.methodNames = new HashSet<String>(methodNames);
|
||||
}
|
||||
|
||||
public void setArgumentValues(List<String> argumentValues)
|
||||
{
|
||||
this.argumentValues = argumentValues;
|
||||
this.argumentQNameValues = new HashSet<QName>(argumentValues.size()*2+1);
|
||||
for (String argumentValue : argumentValues)
|
||||
{
|
||||
QName argumentQNameValue = QName.createQName(argumentValue);
|
||||
argumentQNameValues.add(argumentQNameValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -637,7 +637,7 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest
|
||||
});
|
||||
}
|
||||
|
||||
public void testalfrescoCheckoutDoesntModifyNode()
|
||||
public void testAlfrescoCheckoutDoesNotModifyNode()
|
||||
{
|
||||
String adminUser = AuthenticationUtil.getAdminUserName();
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(adminUser);
|
||||
@@ -659,9 +659,9 @@ public class CheckOutCheckInServiceImplTest extends BaseSpringTest
|
||||
|
||||
cociService.cancelCheckout(copy);
|
||||
modifier = nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIER);
|
||||
// assertEquals("Cancel checkout should not cause the modifier to change!", initModifier, modifier);
|
||||
assertEquals("Cancel checkout should not cause the modifier to change!", initModifier, modifier);
|
||||
modified = nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED);
|
||||
// assertEquals("Cancel checkout should not cause the modified date to change!", initModified, modified);
|
||||
assertEquals("Cancel checkout should not cause the modified date to change!", initModified, modified);
|
||||
|
||||
copy = cociService.checkout(
|
||||
nodeRef,
|
||||
|
@@ -35,8 +35,6 @@ import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.importer.view.NodeContext;
|
||||
import org.alfresco.repo.policy.BehaviourFilter;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationContext;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.repo.transaction.TransactionListener;
|
||||
import org.alfresco.repo.version.Version2Model;
|
||||
import org.alfresco.repo.version.common.VersionUtil;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
@@ -65,16 +63,15 @@ import org.alfresco.service.cmr.version.Version;
|
||||
import org.alfresco.service.cmr.version.VersionService;
|
||||
import org.alfresco.service.cmr.view.ImportPackageHandler;
|
||||
import org.alfresco.service.cmr.view.ImporterBinding;
|
||||
import org.alfresco.service.cmr.view.ImporterBinding.UUID_BINDING;
|
||||
import org.alfresco.service.cmr.view.ImporterException;
|
||||
import org.alfresco.service.cmr.view.ImporterProgress;
|
||||
import org.alfresco.service.cmr.view.ImporterService;
|
||||
import org.alfresco.service.cmr.view.Location;
|
||||
import org.alfresco.service.cmr.view.ImporterBinding.UUID_BINDING;
|
||||
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.hibernate.engine.TransactionHelper;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
@@ -774,7 +771,7 @@ public class ImporterComponent
|
||||
*/
|
||||
public void childrenImported(NodeRef nodeRef)
|
||||
{
|
||||
behaviourFilter.enableBehaviours(nodeRef);
|
||||
behaviourFilter.enableBehaviour(nodeRef);
|
||||
ruleService.enableRules(nodeRef);
|
||||
}
|
||||
|
||||
@@ -845,12 +842,12 @@ public class ImporterComponent
|
||||
}
|
||||
|
||||
// Set node reference on source node
|
||||
Set<QName> disabledBehaviours = getDisabledBehaviours(importedRef.context);
|
||||
Set<QName> nodeTypeAndAspects = getNodeTypeAndAspects(importedRef.context);
|
||||
try
|
||||
{
|
||||
for (QName disabledBehaviour: disabledBehaviours)
|
||||
for (QName typeOrAspect: nodeTypeAndAspects)
|
||||
{
|
||||
behaviourFilter.disableBehaviour(importedRef.context.getNodeRef(), disabledBehaviour);
|
||||
behaviourFilter.disableBehaviour(importedRef.context.getNodeRef(), typeOrAspect);
|
||||
}
|
||||
nodeService.setProperty(importedRef.context.getNodeRef(), importedRef.property, refProperty);
|
||||
if (progress != null)
|
||||
@@ -860,7 +857,10 @@ public class ImporterComponent
|
||||
}
|
||||
finally
|
||||
{
|
||||
behaviourFilter.enableBehaviours(importedRef.context.getNodeRef());
|
||||
for (QName typeOrAspect: nodeTypeAndAspects)
|
||||
{
|
||||
behaviourFilter.enableBehaviour(importedRef.context.getNodeRef(), typeOrAspect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -873,7 +873,7 @@ public class ImporterComponent
|
||||
*/
|
||||
public void error(Throwable e)
|
||||
{
|
||||
behaviourFilter.enableAllBehaviours();
|
||||
behaviourFilter.enableBehaviour();
|
||||
reportError(e);
|
||||
}
|
||||
|
||||
@@ -1001,12 +1001,12 @@ public class ImporterComponent
|
||||
}
|
||||
|
||||
/**
|
||||
* For the given import node, return the behaviours to disable during import
|
||||
* For the given import node, return the type and aspects to import
|
||||
*
|
||||
* @param context import node
|
||||
* @return the disabled behaviours
|
||||
* @return the type and aspects in the import
|
||||
*/
|
||||
private Set<QName> getDisabledBehaviours(ImportNode context)
|
||||
private Set<QName> getNodeTypeAndAspects(ImportNode context)
|
||||
{
|
||||
Set<QName> classNames = new HashSet<QName>();
|
||||
|
||||
@@ -1352,18 +1352,12 @@ public class ImporterComponent
|
||||
throw new ImporterException("Cannot determine child name of node (type: " + nodeType.getName() + ")");
|
||||
}
|
||||
|
||||
// Create initial node (but, first disable behaviour for the node to be created)
|
||||
Set<QName> disabledBehaviours = getDisabledBehaviours(node);
|
||||
List<QName> alreadyDisabledBehaviours = new ArrayList<QName>();
|
||||
for (QName disabledBehaviour: disabledBehaviours)
|
||||
// Disable the import-wide behaviours (because the node doesn't exist, yet)
|
||||
Set<QName> nodeTypeAndAspects = getNodeTypeAndAspects(node);
|
||||
for (QName typeOrAspect: nodeTypeAndAspects)
|
||||
{
|
||||
boolean alreadyDisabled = behaviourFilter.disableBehaviour(disabledBehaviour);
|
||||
if (alreadyDisabled)
|
||||
{
|
||||
alreadyDisabledBehaviours.add(disabledBehaviour);
|
||||
}
|
||||
behaviourFilter.disableBehaviour(typeOrAspect);
|
||||
}
|
||||
disabledBehaviours.removeAll(alreadyDisabledBehaviours);
|
||||
|
||||
// Build initial map of properties
|
||||
Map<QName, Serializable> initialProperties = bindProperties(node);
|
||||
@@ -1403,15 +1397,13 @@ public class ImporterComponent
|
||||
}
|
||||
}
|
||||
|
||||
// Re-enable the import-wide behaviours
|
||||
// Disable behaviour for the node until the complete node (and its children have been imported)
|
||||
for (QName disabledBehaviour : disabledBehaviours)
|
||||
for (QName typeOrAspect: nodeTypeAndAspects)
|
||||
{
|
||||
behaviourFilter.enableBehaviour(disabledBehaviour);
|
||||
}
|
||||
for (QName disabledBehaviour : disabledBehaviours)
|
||||
{
|
||||
behaviourFilter.disableBehaviour(nodeRef, disabledBehaviour);
|
||||
behaviourFilter.enableBehaviour(typeOrAspect);
|
||||
}
|
||||
behaviourFilter.disableBehaviour(nodeRef);
|
||||
// TODO: Replace this with appropriate rule/action import handling
|
||||
ruleService.disableRules(nodeRef);
|
||||
|
||||
|
@@ -2181,17 +2181,14 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
|
||||
*/
|
||||
private void archiveNode(NodeRef nodeRef, StoreRef archiveStoreRef)
|
||||
{
|
||||
boolean wasDisabled = policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
try
|
||||
{
|
||||
archiveNodeImpl(nodeRef, archiveStoreRef);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!wasDisabled)
|
||||
{
|
||||
policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
}
|
||||
policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2256,17 +2253,14 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
|
||||
*/
|
||||
public NodeRef restoreNode(NodeRef archivedNodeRef, NodeRef destinationParentNodeRef, QName assocTypeQName, QName assocQName)
|
||||
{
|
||||
boolean wasDisabled = policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
try
|
||||
{
|
||||
return restoreNodeImpl(archivedNodeRef, destinationParentNodeRef, assocTypeQName, assocQName);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!wasDisabled)
|
||||
{
|
||||
policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
}
|
||||
policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,37 +26,71 @@ import org.alfresco.service.namespace.QName;
|
||||
*
|
||||
* @See org.alfresco.repo.policy.PolicyComponent
|
||||
*
|
||||
* @author David Caruana
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public interface BehaviourFilter
|
||||
{
|
||||
/**
|
||||
* @deprecated Since 4.0 use {@link #enableBehaviour(NodeRef)}
|
||||
*/
|
||||
public void enableBehaviours(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* @deprecated Since 4.0 use {@link #enableBehaviour(NodeRef)}
|
||||
*/
|
||||
public void disableAllBehaviours();
|
||||
|
||||
/**
|
||||
* @deprecated Since 4.0 use {@link #disableBehaviour()}
|
||||
*/
|
||||
public void enableAllBehaviours();
|
||||
|
||||
/**
|
||||
* Disable behaviour for all types
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
*/
|
||||
public void disableBehaviour();
|
||||
|
||||
/**
|
||||
* Disable behaviour for a type or aspect for all nodes.
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
*
|
||||
* @param className the type/aspect behaviour to disable
|
||||
* @return true => already disabled
|
||||
* @param className the type/aspect behaviour to disable
|
||||
*/
|
||||
public boolean disableBehaviour(QName className);
|
||||
public void disableBehaviour(QName className);
|
||||
|
||||
/**
|
||||
* Disable behaviour for specific node
|
||||
* Disable behaviour for specific node and class
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
*
|
||||
* @param nodeRef the node to disable for
|
||||
* @param className the type/aspect behaviour to disable
|
||||
* @return true => already disabled
|
||||
* @param nodeRef the node to disable for
|
||||
* @param className the type/aspect behaviour to disable
|
||||
*/
|
||||
public boolean disableBehaviour(NodeRef nodeRef, QName className);
|
||||
public void disableBehaviour(NodeRef nodeRef, QName className);
|
||||
|
||||
/**
|
||||
* Disable all behaviours for a given node
|
||||
*
|
||||
* @param nodeRef the node to disable for
|
||||
*/
|
||||
public void disableBehaviour(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Enable behaviours for all classes.
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
*/
|
||||
public void enableBehaviour();
|
||||
|
||||
/**
|
||||
* Enable behaviour for all nodes
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
*
|
||||
* @param className the type/aspect behaviour to enable
|
||||
* @param className the type/aspect behaviour to enable
|
||||
*/
|
||||
public void enableBehaviour(QName className);
|
||||
|
||||
@@ -65,53 +99,45 @@ public interface BehaviourFilter
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
*
|
||||
* @param nodeRef the node to enable for
|
||||
* @param className the type/aspect behaviour to enable
|
||||
* @param nodeRef the node to enable for
|
||||
* @param className the type/aspect behaviour to enable or <tt>null</tt> for all classes
|
||||
*/
|
||||
public void enableBehaviour(NodeRef nodeRef, QName className);
|
||||
|
||||
/**
|
||||
* Enable behaviour for a specific node
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
*
|
||||
* @param nodeRef the node to enable for
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public void enableBehaviour(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Enable all behaviours for specific node
|
||||
* Determine if behaviour is globally enabled.
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
*
|
||||
* @param nodeRef the node to enable for
|
||||
* @return true => behaviour is enabled
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public void enableBehaviours(NodeRef nodeRef);
|
||||
public boolean isEnabled();
|
||||
|
||||
/**
|
||||
* Disable all behaviours. Once this method is called the node and class level filters, enableBehaviours and disableBehaviours
|
||||
* methods have no effect, every behaviour is disabled.
|
||||
* EnableAllBehaviours reverses the result of calling this method.
|
||||
* <p>
|
||||
* Calling this method may result in nodes existing in your repository that do not conform to your policies.
|
||||
*
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
* @see #enableAllBehaviours
|
||||
*/
|
||||
public void disableAllBehaviours();
|
||||
|
||||
/**
|
||||
* Enable all behaviours i.e. undo all disable calls - at the global,
|
||||
* node and class level.
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
*/
|
||||
public void enableAllBehaviours();
|
||||
|
||||
/**
|
||||
* Determine if behaviour is enabled across all nodes.
|
||||
* Determine if behaviour is enabled for a class.
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
*
|
||||
* @param className the behaviour to test for
|
||||
* @return true => behaviour is enabled
|
||||
* @param className the behaviour to test for
|
||||
* @return true => behaviour is enabled
|
||||
*/
|
||||
public boolean isEnabled(QName className);
|
||||
|
||||
/**
|
||||
* Determine if behaviour is enabled for specific node.
|
||||
* Determine if behaviour is enabled for specific node and class.
|
||||
* <p>
|
||||
* Note: A node behaviour is enabled only when:
|
||||
* a) the behaviour is not disabled across all nodes
|
||||
@@ -119,18 +145,28 @@ public interface BehaviourFilter
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
*
|
||||
* @param nodeRef the node to test for
|
||||
* @param className the behaviour to test for
|
||||
* @return true => behaviour is enabled
|
||||
* @param nodeRef the node to test for
|
||||
* @param className the behaviour to test for
|
||||
* @return true => behaviour is enabled
|
||||
*/
|
||||
public boolean isEnabled(NodeRef nodeRef, QName className);
|
||||
|
||||
/**
|
||||
* Determine if any behaviours have been disabled?
|
||||
* Determine if behaviour is enabled for a specific node.
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
*
|
||||
* @return true => behaviours have been filtered
|
||||
* @param nodeRef the node to test for
|
||||
* @return true => behaviour is enabled
|
||||
*/
|
||||
public boolean isEnabled(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Determine if any behaviours have been disabled or altered.
|
||||
* <p>
|
||||
* The change applies <b>ONLY</b> to the current transaction.
|
||||
*
|
||||
* @return true => behaviours have been altered
|
||||
*/
|
||||
public boolean isActivated();
|
||||
}
|
||||
|
@@ -18,33 +18,66 @@
|
||||
*/
|
||||
package org.alfresco.repo.policy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.repo.transaction.TransactionalResourceHelper;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.lang.mutable.MutableInt;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.surf.util.ParameterCheck;
|
||||
|
||||
/**
|
||||
* Implementation of Behaviour Filter. All methods operate on transactionally-bound
|
||||
* resources. Behaviour will therefore never span transactions; the filter state has
|
||||
* the same lifespan as the transaction in which it was created.
|
||||
* <p/>
|
||||
* Since 4.0, the behaviour enabling/disabling is recorded using reference counting,
|
||||
* meaning that the outermost disable call in a stack has an effective veto. Use
|
||||
* proper try-finally patterns to ensure behaviour is released after it is no longer
|
||||
* needed.
|
||||
* <pre><code>
|
||||
* behaviourFilter.disableBehaviour(abc);
|
||||
* try
|
||||
* {
|
||||
* behaviourFilter.disableBehaviour(abc);
|
||||
* try
|
||||
* {
|
||||
* // Do something that might have triggered 'abc' but will not
|
||||
* }
|
||||
* finally
|
||||
* {
|
||||
* behaviourFilter.enableBehaviour(abc);
|
||||
* }
|
||||
* // Do something that might have triggered 'abc' but will not despite the last enable call
|
||||
* }
|
||||
* finally
|
||||
* {
|
||||
* behaviourFilter.enableBehaviour(abc);
|
||||
* }
|
||||
* </code></pre>
|
||||
* <p/>
|
||||
* <b>Multitenancy and disabling by <tt>NodeRef</tt>:</b><br/>
|
||||
* Conversions based on the current tenant context are done automatically.
|
||||
*
|
||||
* @author David Caruana
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class BehaviourFilterImpl implements BehaviourFilter
|
||||
{
|
||||
private static final String KEY_GLOBAL_FILTER = "BehaviourFilterImpl.gloalFilter";
|
||||
private static final String KEY_CLASS_FILTER = "BehaviourFilterImpl.classFilter";
|
||||
private static final String KEY_NODEREF_FILTER = "BehaviourFilterImpl.nodeRefFilter";
|
||||
private static final String KEY_FILTER_COUNT = "BehaviourFilterImpl.filterCount";
|
||||
private static final String KEY_GLOBAL_FILTERS = "BehaviourFilterImpl.globalFilters";
|
||||
private static final String KEY_CLASS_FILTERS = "BehaviourFilterImpl.classFilters";
|
||||
private static final String KEY_INSTANCE_CLASS_FILTERS = "BehaviourFilterImpl.instanceClassFilters";
|
||||
private static final String KEY_INSTANCE_FILTERS = "BehaviourFilterImpl.instanceFilters";
|
||||
|
||||
private static final Log logger = LogFactory.getLog(BehaviourFilterImpl.class);
|
||||
|
||||
// Dictionary Service
|
||||
private DictionaryService dictionaryService;
|
||||
|
||||
// Tenant Service
|
||||
private TenantService tenantService;
|
||||
|
||||
/**
|
||||
@@ -62,150 +95,389 @@ public class BehaviourFilterImpl implements BehaviourFilter
|
||||
{
|
||||
this.tenantService = tenantService;
|
||||
}
|
||||
|
||||
public boolean disableBehaviour(QName className)
|
||||
{
|
||||
List<QName> classFilters = TransactionalResourceHelper.getList(KEY_CLASS_FILTER);
|
||||
boolean alreadyDisabled = classFilters.contains(className);
|
||||
if (!alreadyDisabled)
|
||||
{
|
||||
classFilters.add(className);
|
||||
}
|
||||
return alreadyDisabled;
|
||||
}
|
||||
|
||||
public boolean disableBehaviour(NodeRef nodeRef, QName className)
|
||||
{
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
Map<NodeRef,List<QName>> nodeRefFilters = TransactionalResourceHelper.getMap(KEY_NODEREF_FILTER);
|
||||
List<QName> classNames = nodeRefFilters.get(nodeRef);
|
||||
if (classNames == null)
|
||||
{
|
||||
classNames = new ArrayList<QName>();
|
||||
nodeRefFilters.put(nodeRef, classNames);
|
||||
}
|
||||
boolean alreadyDisabled = classNames.contains(className);
|
||||
if (!alreadyDisabled)
|
||||
{
|
||||
classNames.add(className);
|
||||
}
|
||||
return alreadyDisabled;
|
||||
}
|
||||
|
||||
public void enableBehaviour(QName className)
|
||||
{
|
||||
List<QName> classFilters = TransactionalResourceHelper.getList(KEY_CLASS_FILTER);
|
||||
classFilters.remove(className);
|
||||
}
|
||||
|
||||
public void enableBehaviour(NodeRef nodeRef, QName className)
|
||||
{
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
Map<NodeRef,List<QName>> nodeRefFilters = TransactionalResourceHelper.getMap(KEY_NODEREF_FILTER);
|
||||
List<QName> classNames = nodeRefFilters.get(nodeRef);
|
||||
if (classNames != null)
|
||||
{
|
||||
classNames.remove(className);
|
||||
if (classNames.size() == 0)
|
||||
{
|
||||
nodeRefFilters.remove(nodeRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
// TODO
|
||||
public void enableBehaviours(NodeRef nodeRef)
|
||||
{
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
Map<NodeRef,List<QName>> nodeRefFilters = TransactionalResourceHelper.getMap(KEY_NODEREF_FILTER);
|
||||
nodeRefFilters.remove(nodeRef);
|
||||
enableBehaviour(nodeRef);
|
||||
}
|
||||
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
// TODO
|
||||
public void disableAllBehaviours()
|
||||
{
|
||||
TransactionalResourceHelper.setBoolean(KEY_GLOBAL_FILTER);
|
||||
disableBehaviour();
|
||||
}
|
||||
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
// TODO
|
||||
public void enableAllBehaviours()
|
||||
{
|
||||
TransactionalResourceHelper.resetBoolean(KEY_GLOBAL_FILTER);
|
||||
|
||||
Map<NodeRef,List<QName>> filters = TransactionalResourceHelper.getMap(KEY_NODEREF_FILTER);
|
||||
filters.clear();
|
||||
enableBehaviour();
|
||||
}
|
||||
|
||||
public boolean isEnabled(NodeRef nodeRef, QName className)
|
||||
@Override
|
||||
public void disableBehaviour()
|
||||
{
|
||||
if(TransactionalResourceHelper.testBoolean(KEY_GLOBAL_FILTER))
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
return false;
|
||||
logger.debug("Behaviour: DISABLE (" + AlfrescoTransactionSupport.getTransactionId() + "): ALL");
|
||||
}
|
||||
|
||||
// check global filters
|
||||
if (!isEnabled(className))
|
||||
|
||||
TransactionalResourceHelper.incrementCount(KEY_FILTER_COUNT);
|
||||
|
||||
TransactionalResourceHelper.incrementCount(KEY_GLOBAL_FILTERS);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
return false;
|
||||
logger.debug(" Now: " + TransactionalResourceHelper.getCount(KEY_GLOBAL_FILTERS));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableBehaviour(QName className)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Behaviour: DISABLE (" + AlfrescoTransactionSupport.getTransactionId() + "): " + className);
|
||||
}
|
||||
ParameterCheck.mandatory("className", className);
|
||||
|
||||
TransactionalResourceHelper.incrementCount(KEY_FILTER_COUNT);
|
||||
|
||||
Map<QName, MutableInt> classFilters = TransactionalResourceHelper.getMap(KEY_CLASS_FILTERS);
|
||||
MutableInt filter = classFilters.get(className);
|
||||
if (filter == null)
|
||||
{
|
||||
filter = new MutableInt(1); // Already incremented
|
||||
classFilters.put(className, filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
filter.increment();
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(" Now: " + filter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableBehaviour(NodeRef nodeRef, QName className)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
ParameterCheck.mandatory("className", className);
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
// check node level filters
|
||||
Map<NodeRef,List<QName>> filters = TransactionalResourceHelper.getMap(KEY_NODEREF_FILTER);
|
||||
List<QName> nodeClassFilters = filters.get(nodeRef);
|
||||
if (nodeClassFilters != null)
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
boolean filtered = nodeClassFilters.contains(className);
|
||||
if (filtered)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (QName filterName : nodeClassFilters)
|
||||
{
|
||||
filtered = dictionaryService.isSubClass(className, filterName);
|
||||
if (filtered)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
logger.debug("Behaviour: DISABLE (" + AlfrescoTransactionSupport.getTransactionId() + "): " + nodeRef + "/" + className);
|
||||
}
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
return true;
|
||||
TransactionalResourceHelper.incrementCount(KEY_FILTER_COUNT);
|
||||
|
||||
Map<NodeRef, Map<QName, MutableInt>> instanceClassFilters = TransactionalResourceHelper.getMap(KEY_INSTANCE_CLASS_FILTERS);
|
||||
Map<QName, MutableInt> classFilters = instanceClassFilters.get(nodeRef);
|
||||
if (classFilters == null)
|
||||
{
|
||||
classFilters = new HashMap<QName, MutableInt>(3);
|
||||
instanceClassFilters.put(nodeRef, classFilters);
|
||||
}
|
||||
MutableInt filter = classFilters.get(className);
|
||||
if (filter == null)
|
||||
{
|
||||
filter = new MutableInt(0);
|
||||
classFilters.put(className, filter);
|
||||
}
|
||||
filter.increment();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(" Now: " + filter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableBehaviour(NodeRef nodeRef)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Behaviour: DISABLE (" + AlfrescoTransactionSupport.getTransactionId() + "): " + nodeRef + "/ALL:");
|
||||
}
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
TransactionalResourceHelper.incrementCount(KEY_FILTER_COUNT);
|
||||
|
||||
Map<NodeRef, MutableInt> instanceFilters = TransactionalResourceHelper.getMap(KEY_INSTANCE_FILTERS);
|
||||
MutableInt filter = instanceFilters.get(nodeRef);
|
||||
if (filter == null)
|
||||
{
|
||||
filter = new MutableInt(0);
|
||||
instanceFilters.put(nodeRef, filter);
|
||||
}
|
||||
filter.increment();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(" Now:" + filter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableBehaviour()
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Behaviour: ENABLE (" + AlfrescoTransactionSupport.getTransactionId() + "): ALL");
|
||||
}
|
||||
|
||||
TransactionalResourceHelper.decrementCount(KEY_FILTER_COUNT, false);
|
||||
|
||||
TransactionalResourceHelper.decrementCount(KEY_GLOBAL_FILTERS, false);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(" Now: " + TransactionalResourceHelper.getCount(KEY_GLOBAL_FILTERS));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableBehaviour(QName className)
|
||||
{
|
||||
ParameterCheck.mandatory("className", className);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Behaviour: ENABLE (" + AlfrescoTransactionSupport.getTransactionId() + "): " + className);
|
||||
}
|
||||
|
||||
TransactionalResourceHelper.decrementCount(KEY_FILTER_COUNT, false);
|
||||
|
||||
if (!TransactionalResourceHelper.isResourcePresent(KEY_CLASS_FILTERS))
|
||||
{
|
||||
// Nothing was disabled
|
||||
return;
|
||||
}
|
||||
Map<QName, MutableInt> classFilters = TransactionalResourceHelper.getMap(KEY_CLASS_FILTERS);
|
||||
MutableInt filter = classFilters.get(className);
|
||||
if (filter == null)
|
||||
{
|
||||
// Class was not disabled
|
||||
return;
|
||||
}
|
||||
else if (filter.intValue() <= 0)
|
||||
{
|
||||
// Can't go below zero for this
|
||||
}
|
||||
else
|
||||
{
|
||||
filter.decrement();
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(" Now: "+ filter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableBehaviour(NodeRef nodeRef, QName className)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
ParameterCheck.mandatory("className", className);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Behaviour: ENABLE (" + AlfrescoTransactionSupport.getTransactionId() + "): " + nodeRef + "/" + className);
|
||||
}
|
||||
|
||||
TransactionalResourceHelper.decrementCount(KEY_FILTER_COUNT, false);
|
||||
|
||||
if (!TransactionalResourceHelper.isResourcePresent(KEY_INSTANCE_CLASS_FILTERS))
|
||||
{
|
||||
// Nothing was disabled
|
||||
return;
|
||||
}
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
Map<NodeRef, Map<QName, MutableInt>> instanceClassFilters = TransactionalResourceHelper.getMap(KEY_INSTANCE_CLASS_FILTERS);
|
||||
Map<QName, MutableInt> classFilters = instanceClassFilters.get(nodeRef);
|
||||
if (classFilters == null)
|
||||
{
|
||||
// Instance classes were not disabled
|
||||
return;
|
||||
}
|
||||
MutableInt filter = classFilters.get(className);
|
||||
if (filter == null)
|
||||
{
|
||||
// Class was not disabled
|
||||
return;
|
||||
}
|
||||
else if (filter.intValue() <= 0)
|
||||
{
|
||||
// Can't go below zero for this
|
||||
}
|
||||
else
|
||||
{
|
||||
filter.decrement();
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(" Now: "+ filter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableBehaviour(NodeRef nodeRef)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Behaviour: ENABLE (" + AlfrescoTransactionSupport.getTransactionId() + "): " + nodeRef + "/ALL");
|
||||
}
|
||||
|
||||
TransactionalResourceHelper.decrementCount(KEY_FILTER_COUNT, false);
|
||||
|
||||
if (!TransactionalResourceHelper.isResourcePresent(KEY_INSTANCE_FILTERS))
|
||||
{
|
||||
// Nothing was disabled
|
||||
return;
|
||||
}
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
Map<NodeRef, MutableInt> instanceFilters = TransactionalResourceHelper.getMap(KEY_INSTANCE_FILTERS);
|
||||
MutableInt filter = instanceFilters.get(nodeRef);
|
||||
if (filter == null)
|
||||
{
|
||||
// Instance was not disabled
|
||||
return;
|
||||
}
|
||||
else if (filter.intValue() <= 0)
|
||||
{
|
||||
// Can't go below zero for this
|
||||
}
|
||||
else
|
||||
{
|
||||
filter.decrement();
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(" Now:" + filter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return TransactionalResourceHelper.getCount(KEY_GLOBAL_FILTERS) <= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(QName className)
|
||||
{
|
||||
if(TransactionalResourceHelper.testBoolean(KEY_GLOBAL_FILTER))
|
||||
ParameterCheck.mandatory("className", className);
|
||||
|
||||
// Check the global, first
|
||||
if (!isEnabled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// check global class filters
|
||||
List<QName> classFilters = TransactionalResourceHelper.getList(KEY_CLASS_FILTER);
|
||||
boolean filtered = classFilters.contains(className);
|
||||
if (filtered)
|
||||
if (!TransactionalResourceHelper.isResourcePresent(KEY_CLASS_FILTERS))
|
||||
{
|
||||
// Nothing was disabled
|
||||
return true;
|
||||
}
|
||||
Map<QName, MutableInt> classFilters = TransactionalResourceHelper.getMap(KEY_CLASS_FILTERS);
|
||||
MutableInt classFilter = classFilters.get(className);
|
||||
return (classFilter == null) || classFilter.intValue() <= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(NodeRef nodeRef, QName className)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
ParameterCheck.mandatory("className", className);
|
||||
|
||||
// Check the class (includes global) and instance, first
|
||||
if (!isEnabled(className) || !isEnabled(nodeRef))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (QName classFilter : classFilters)
|
||||
|
||||
if (!TransactionalResourceHelper.isResourcePresent(KEY_INSTANCE_CLASS_FILTERS))
|
||||
{
|
||||
filtered = dictionaryService.isSubClass(className, classFilter);
|
||||
if (filtered)
|
||||
// Nothing was disabled
|
||||
return true;
|
||||
}
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
Map<NodeRef, Map<QName, MutableInt>> instanceClassFilters = TransactionalResourceHelper.getMap(KEY_INSTANCE_CLASS_FILTERS);
|
||||
Map<QName, MutableInt> classFilters = instanceClassFilters.get(nodeRef);
|
||||
if (classFilters == null)
|
||||
{
|
||||
// Instance classes were not disabled
|
||||
return true;
|
||||
}
|
||||
for (QName classCheck : classFilters.keySet())
|
||||
{
|
||||
// Ignore if it is not part of the hierarchy we are requesting
|
||||
if (!dictionaryService.isSubClass(className, classCheck))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
MutableInt filter = classFilters.get(className);
|
||||
if (filter != null && filter.intValue() > 0)
|
||||
{
|
||||
// Class was disabled
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isActivated()
|
||||
@Override
|
||||
public boolean isEnabled(NodeRef nodeRef)
|
||||
{
|
||||
List<QName> classFilters = TransactionalResourceHelper.getList(KEY_CLASS_FILTER);
|
||||
Map<NodeRef,List<QName>> nodeRefFilters = TransactionalResourceHelper.getMap(KEY_NODEREF_FILTER);
|
||||
boolean globalFlag = TransactionalResourceHelper.testBoolean(KEY_GLOBAL_FILTER);
|
||||
return ((!classFilters.isEmpty()) || (!nodeRefFilters.isEmpty()) || globalFlag);
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
|
||||
// Check the class (includes global) and instance, first
|
||||
if (!isEnabled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TransactionalResourceHelper.isResourcePresent(KEY_INSTANCE_FILTERS))
|
||||
{
|
||||
// Nothing was disabled
|
||||
return true;
|
||||
}
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
Map<NodeRef, MutableInt> instanceFilters = TransactionalResourceHelper.getMap(KEY_INSTANCE_FILTERS);
|
||||
MutableInt filter = instanceFilters.get(nodeRef);
|
||||
if (filter != null && filter.intValue() > 0)
|
||||
{
|
||||
// Instance was disabled
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActivated()
|
||||
{
|
||||
return TransactionalResourceHelper.getCount(KEY_FILTER_COUNT) > 0;
|
||||
}
|
||||
}
|
||||
|
@@ -32,6 +32,7 @@ import org.alfresco.repo.policy.Policy.Arg;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
@@ -50,6 +51,7 @@ public class PolicyComponentTransactionTest extends TestCase
|
||||
private static ApplicationContext applicationContext = ApplicationContextHelper.getApplicationContext();
|
||||
private static ClassPolicyDelegate<SideEffectTestPolicy> sideEffectDelegate = null;
|
||||
private PolicyComponent policyComponent;
|
||||
private BehaviourFilter behaviourFilter;
|
||||
private TransactionService trxService;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
|
||||
@@ -68,6 +70,7 @@ public class PolicyComponentTransactionTest extends TestCase
|
||||
|
||||
// retrieve policy component
|
||||
this.policyComponent = (PolicyComponent)applicationContext.getBean("policyComponent");
|
||||
this.behaviourFilter = (BehaviourFilter) applicationContext.getBean("policyBehaviourFilter");
|
||||
this.trxService = (TransactionService) applicationContext.getBean("transactionComponent");
|
||||
this.authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent");
|
||||
this.authenticationComponent.setSystemUserAsCurrentUser();
|
||||
@@ -283,9 +286,100 @@ public class PolicyComponentTransactionTest extends TestCase
|
||||
{
|
||||
try { userTransaction2.rollback(); } catch (IllegalStateException ee) {}
|
||||
throw e;
|
||||
}
|
||||
|
||||
NodeRef nodeRef = new NodeRef(TEST_NAMESPACE, "test", "123");
|
||||
// Check enabling and disabling of behaviours within the transaction
|
||||
// We disable multiple times and enable, including enabling when not disabled
|
||||
UserTransaction userTransaction3 = trxService.getUserTransaction();
|
||||
try
|
||||
{
|
||||
userTransaction3.begin();
|
||||
|
||||
// Check all enabled to start
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, true, true);
|
||||
|
||||
// Check instance with nesting
|
||||
behaviourFilter.enableBehaviour(nodeRef);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, true, true);
|
||||
behaviourFilter.disableBehaviour(nodeRef);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, false, false);
|
||||
behaviourFilter.disableBehaviour(nodeRef);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, false, false);
|
||||
behaviourFilter.enableBehaviour(nodeRef);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, false, false);
|
||||
behaviourFilter.enableBehaviour(nodeRef);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, true, true);
|
||||
|
||||
// Check class and instance with nesting
|
||||
behaviourFilter.enableBehaviour(nodeRef, BASE_TYPE);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, true, true);
|
||||
behaviourFilter.disableBehaviour(nodeRef, BASE_TYPE);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, false, true);
|
||||
behaviourFilter.disableBehaviour(nodeRef, BASE_TYPE);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, false, true);
|
||||
behaviourFilter.enableBehaviour(nodeRef, BASE_TYPE);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, false, true);
|
||||
behaviourFilter.enableBehaviour(nodeRef, BASE_TYPE);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, true, true);
|
||||
|
||||
// Check class with nesting
|
||||
behaviourFilter.enableBehaviour(BASE_TYPE);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, true, true);
|
||||
behaviourFilter.disableBehaviour(BASE_TYPE);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, false, false, true);
|
||||
behaviourFilter.disableBehaviour(BASE_TYPE);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, false, false, true);
|
||||
behaviourFilter.enableBehaviour(BASE_TYPE);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, false, false, true);
|
||||
behaviourFilter.enableBehaviour(BASE_TYPE);
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, true, true);
|
||||
|
||||
// Check global with nesting
|
||||
behaviourFilter.enableBehaviour();
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, true, true);
|
||||
behaviourFilter.disableBehaviour();
|
||||
checkBehaviour(BASE_TYPE, nodeRef, false, false, false, false);
|
||||
behaviourFilter.disableBehaviour();
|
||||
checkBehaviour(BASE_TYPE, nodeRef, false, false, false, false);
|
||||
behaviourFilter.enableBehaviour();
|
||||
checkBehaviour(BASE_TYPE, nodeRef, false, false, false, false);
|
||||
behaviourFilter.enableBehaviour();
|
||||
checkBehaviour(BASE_TYPE, nodeRef, true, true, true, true);
|
||||
|
||||
userTransaction3.commit();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
try { userTransaction3.rollback(); } catch (IllegalStateException ee) {}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param className the class to check
|
||||
* @param nodeRef the node instance to check
|
||||
* @param globalEnabled <tt>true</tt> if the global filter should be enabled
|
||||
* @param classEnabled <tt>true</tt> if the class should be enabled
|
||||
* @param classInstanceEnabled <tt>true</tt> if the class and instance should be enabled
|
||||
* @param instanceEnabled <tt>true</tt> if the instance should be enabled
|
||||
*/
|
||||
private void checkBehaviour(
|
||||
QName className, NodeRef nodeRef,
|
||||
boolean globalEnabled,
|
||||
boolean classEnabled,
|
||||
boolean classInstanceEnabled,
|
||||
boolean instanceEnabled)
|
||||
|
||||
{
|
||||
assertEquals("Incorrect behaviour state: global: ", globalEnabled, behaviourFilter.isEnabled());
|
||||
assertEquals("Incorrect behaviour state: class: ", classEnabled, behaviourFilter.isEnabled(className));
|
||||
assertEquals("Incorrect behaviour state: classAndInstance", classInstanceEnabled, behaviourFilter.isEnabled(nodeRef, className));
|
||||
assertEquals("Incorrect behaviour state: instance", instanceEnabled, behaviourFilter.isEnabled(nodeRef));
|
||||
assertEquals("'Active' flag incorrect: ",
|
||||
!(globalEnabled && classEnabled && classInstanceEnabled && instanceEnabled),
|
||||
behaviourFilter.isActivated());
|
||||
}
|
||||
|
||||
//
|
||||
// Behaviour Implementations
|
||||
|
@@ -73,13 +73,13 @@ public class PublishingEventProcessor
|
||||
{
|
||||
try
|
||||
{
|
||||
behaviourFilter.disableAllBehaviours();
|
||||
behaviourFilter.disableBehaviour();
|
||||
channel.publishEvent(event);
|
||||
sendStatusUpdate(channel, event.getStatusUpdate());
|
||||
}
|
||||
finally
|
||||
{
|
||||
behaviourFilter.enableAllBehaviours();
|
||||
behaviourFilter.enableBehaviour();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@@ -378,7 +378,7 @@ public class UpdateTagScopesActionExecuter extends ActionExecuterAbstractBase
|
||||
|
||||
// Changing the tag scope values is a system operation
|
||||
// As such, don't fire policies/behaviours during this
|
||||
behaviourFilter.disableAllBehaviours();
|
||||
behaviourFilter.disableBehaviour();
|
||||
|
||||
// Get the current tags
|
||||
ContentReader contentReader = contentService.getReader(tagScopeNode, ContentModel.PROP_TAGSCOPE_CACHE);
|
||||
@@ -452,7 +452,7 @@ public class UpdateTagScopesActionExecuter extends ActionExecuterAbstractBase
|
||||
|
||||
// We're done making our changes
|
||||
// Allow behaviours to fire again if they want to
|
||||
behaviourFilter.enableAllBehaviours();
|
||||
behaviourFilter.enableBehaviour();
|
||||
|
||||
// Log this if required
|
||||
if(logger.isDebugEnabled())
|
||||
|
@@ -277,11 +277,27 @@ public class AlfrescoTransactionSupportTest extends TestCase
|
||||
{
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
// Check map access
|
||||
Map<String, String> map = TransactionalResourceHelper.getMap("abc");
|
||||
assertNotNull("Map not created", map);
|
||||
map.put("1", "ONE");
|
||||
Map<String, String> mapCheck = TransactionalResourceHelper.getMap("abc");
|
||||
assertTrue("Same map not retrieved", map == mapCheck);
|
||||
// Check counter
|
||||
assertEquals("Transactional count incorrect. ", 0, TransactionalResourceHelper.getCount("myCount"));
|
||||
assertEquals("Transactional count incorrect. ", -1, TransactionalResourceHelper.decrementCount("myCount", true));
|
||||
assertEquals("Transactional count incorrect. ", -2, TransactionalResourceHelper.decrementCount("myCount", true));
|
||||
assertEquals("Transactional count incorrect. ", -2, TransactionalResourceHelper.getCount("myCount"));
|
||||
assertEquals("Transactional count incorrect. ", -1, TransactionalResourceHelper.incrementCount("myCount"));
|
||||
assertEquals("Transactional count incorrect. ", 0, TransactionalResourceHelper.incrementCount("myCount"));
|
||||
assertEquals("Transactional count incorrect. ", 1, TransactionalResourceHelper.incrementCount("myCount"));
|
||||
assertEquals("Transactional count incorrect. ", 1, TransactionalResourceHelper.getCount("myCount"));
|
||||
assertEquals("Transactional count incorrect. ", 1, TransactionalResourceHelper.getCount("myCount"));
|
||||
TransactionalResourceHelper.resetCount("myCount");
|
||||
assertEquals("Transactional count incorrect. ", 0, TransactionalResourceHelper.getCount("myCount"));
|
||||
assertEquals("Transactional count incorrect. ", 0, TransactionalResourceHelper.decrementCount("myCount", false));
|
||||
assertEquals("Transactional count incorrect. ", 0, TransactionalResourceHelper.decrementCount("myCount", false));
|
||||
// Done
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
@@ -26,6 +26,8 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.apache.commons.lang.mutable.MutableInt;
|
||||
|
||||
/**
|
||||
* Helper class that will look up or create transactional resources.
|
||||
* This shortcuts some of the "<i>if not existing, then create</i>" code.
|
||||
@@ -35,6 +37,83 @@ import java.util.TreeSet;
|
||||
*/
|
||||
public abstract class TransactionalResourceHelper
|
||||
{
|
||||
/**
|
||||
* Get the current count value for a named key
|
||||
*
|
||||
* @param resourceKey the key to count against
|
||||
* @return the current value for the named key
|
||||
*/
|
||||
public static final int getCount(Object resourceKey)
|
||||
{
|
||||
MutableInt counter = (MutableInt) AlfrescoTransactionSupport.getResource(resourceKey);
|
||||
return counter == null ? 0 : counter.intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the current count value for a named key. After this operation, the effective
|
||||
* value will be 0.
|
||||
*
|
||||
* @param resourceKey the key to count against
|
||||
*/
|
||||
public static final void resetCount(Object resourceKey)
|
||||
{
|
||||
AlfrescoTransactionSupport.unbindResource(resourceKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment a count value for named key
|
||||
*
|
||||
* @param resourceKey the key to count against
|
||||
* @return the newly-incremented value
|
||||
*/
|
||||
public static final int incrementCount(Object resourceKey)
|
||||
{
|
||||
MutableInt counter = (MutableInt) AlfrescoTransactionSupport.getResource(resourceKey);
|
||||
if (counter == null)
|
||||
{
|
||||
counter = new MutableInt(0);
|
||||
AlfrescoTransactionSupport.bindResource(resourceKey, counter);
|
||||
}
|
||||
counter.increment();
|
||||
return counter.intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement a count value for a named key
|
||||
*
|
||||
* @param resourceKey the key to count against
|
||||
* @param allowNegative <tt>true</tt> to allow negative values otherwise zero will be the floor
|
||||
* @return the newly-decremented value (negative, if allowed)
|
||||
*/
|
||||
public static final int decrementCount(Object resourceKey, boolean allowNegative)
|
||||
{
|
||||
MutableInt counter = (MutableInt) AlfrescoTransactionSupport.getResource(resourceKey);
|
||||
if (counter == null)
|
||||
{
|
||||
counter = new MutableInt(0);
|
||||
AlfrescoTransactionSupport.bindResource(resourceKey, counter);
|
||||
}
|
||||
if (counter.intValue() > 0 || allowNegative)
|
||||
{
|
||||
counter.decrement();
|
||||
}
|
||||
return counter.intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Support method to determine if there is already a resource associated with the
|
||||
* given key. This method allows quick conditional checking of the key without
|
||||
* building a new collection.
|
||||
*
|
||||
* @param resourceKey the key of the resource to check
|
||||
* @return <tt>true</tt> if a resource is already present at the key
|
||||
*/
|
||||
public static final boolean isResourcePresent(Object resourceKey)
|
||||
{
|
||||
Object resource = AlfrescoTransactionSupport.getResource(resourceKey);
|
||||
return resource != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support method to retrieve or create and bind a <tt>HashMap</tt> to the current transaction.
|
||||
*
|
||||
@@ -107,52 +186,4 @@ public abstract class TransactionalResourceHelper
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support method to set a boolean (true) value in the current transaction.
|
||||
* @param resourceKey the key under which the resource will be stored
|
||||
* @return true - the value of resourceKey, was set to true, false - the value was already true
|
||||
*/
|
||||
public static final boolean setBoolean(Object resourceKey)
|
||||
{
|
||||
Boolean value = AlfrescoTransactionSupport.getResource(resourceKey);
|
||||
if(value == null)
|
||||
{
|
||||
AlfrescoTransactionSupport.bindResource(resourceKey, Boolean.TRUE);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support method to reset (make false) a boolean value in the current transaction.
|
||||
* @param resourceKey the key under which the resource is stored.
|
||||
*/
|
||||
public static final void resetBoolean(Object resourceKey)
|
||||
{
|
||||
Boolean value = AlfrescoTransactionSupport.getResource(resourceKey);
|
||||
if(value == null)
|
||||
{
|
||||
AlfrescoTransactionSupport.unbindResource(resourceKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a boolean value in the current transaction
|
||||
* @param resourceKey the key under which the resource will be stored
|
||||
* @return true - thre is, false no.
|
||||
*/
|
||||
public static final boolean testBoolean(Object resourceKey)
|
||||
{
|
||||
Boolean value = AlfrescoTransactionSupport.getResource(resourceKey);
|
||||
if(value == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -901,7 +901,7 @@ public class RepoTransferReceiverImpl implements TransferReceiver,
|
||||
XMLTransferManifestReader reader = new XMLTransferManifestReader(processor);
|
||||
|
||||
//behaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
behaviourFilter.disableAllBehaviours();
|
||||
behaviourFilter.disableBehaviour();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -909,8 +909,7 @@ public class RepoTransferReceiverImpl implements TransferReceiver,
|
||||
}
|
||||
finally
|
||||
{
|
||||
// behaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
behaviourFilter.enableAllBehaviours();
|
||||
behaviourFilter.enableBehaviour();
|
||||
}
|
||||
parser.reset();
|
||||
}
|
||||
|
@@ -208,11 +208,7 @@ public class Version2ServiceImpl extends VersionServiceImpl implements VersionSe
|
||||
// of the version label, to affect the auditable properties on the node that
|
||||
// is being versioned.
|
||||
// So, disable the auditable aspect on that node for now
|
||||
boolean disableAuditable = policyBehaviourFilter.isEnabled(ContentModel.ASPECT_AUDITABLE);
|
||||
if(disableAuditable)
|
||||
{
|
||||
policyBehaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||
}
|
||||
policyBehaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||
|
||||
// If the version aspect is not there then add it to the 'live' (versioned) node
|
||||
if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE) == false)
|
||||
@@ -364,10 +360,7 @@ public class Version2ServiceImpl extends VersionServiceImpl implements VersionSe
|
||||
version.getVersionLabel());
|
||||
|
||||
// Re-enable the auditable aspect (if we turned it off earlier)
|
||||
if(disableAuditable)
|
||||
{
|
||||
policyBehaviourFilter.enableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||
}
|
||||
policyBehaviourFilter.enableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||
|
||||
// Invoke the policy behaviour
|
||||
invokeAfterCreateVersion(nodeRef, version);
|
||||
|
Reference in New Issue
Block a user