package org.alfresco.repo.policy; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.transaction.UserTransaction; import junit.framework.TestCase; import org.alfresco.model.ContentModel; import org.alfresco.repo.dictionary.DictionaryBootstrap; import org.alfresco.repo.dictionary.DictionaryDAO; import org.alfresco.repo.node.NodeServicePolicies.OnCreateNodePolicy; import org.alfresco.repo.nodelocator.CompanyHomeNodeLocator; import org.alfresco.repo.nodelocator.NodeLocatorService; import org.alfresco.repo.policy.Behaviour.NotificationFrequency; 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.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; import org.alfresco.test_category.OwnJVMTestsCategory; import org.alfresco.util.ApplicationContextHelper; import org.junit.experimental.categories.Category; import org.springframework.context.ApplicationContext; /** * Test Transaction-level Policies */ @Category(OwnJVMTestsCategory.class) public class PolicyComponentTransactionTest extends TestCase { private static final String TEST_MODEL = "org/alfresco/repo/policy/policycomponenttest_model.xml"; private static final String TEST_NAMESPACE = "http://www.alfresco.org/test/policycomponenttest/1.0"; private static QName BASE_TYPE = QName.createQName(TEST_NAMESPACE, "base"); private static QName FILE_TYPE = QName.createQName(TEST_NAMESPACE, "file"); private static QName A_TYPE = QName.createQName(TEST_NAMESPACE, "a_type"); private static QName B_TYPE = QName.createQName(TEST_NAMESPACE, "b_type"); private static QName C_TYPE = QName.createQName(TEST_NAMESPACE, "c_type"); private static ApplicationContext applicationContext = ApplicationContextHelper.getApplicationContext(); private static ClassPolicyDelegate sideEffectDelegate = null; private PolicyComponent policyComponent; private BehaviourFilter behaviourFilter; private TransactionService trxService; private AuthenticationComponent authenticationComponent; private NodeService nodeService; private NodeLocatorService nodeLocatorService; private NodeRef companyHome; private TestOnCreateNodePolicy aTypeBehavior; private TestOnCreateNodePolicy bTypeBehavior; private TestOnCreateNodePolicy cTypeBehavior; @Override protected void setUp() throws Exception { // initialise policy test model DictionaryBootstrap bootstrap = new DictionaryBootstrap(); List bootstrapModels = new ArrayList(); bootstrapModels.add(TEST_MODEL); bootstrap.setModels(bootstrapModels); bootstrap.setDictionaryDAO((DictionaryDAO)applicationContext.getBean("dictionaryDAO")); bootstrap.setTenantService((TenantService)applicationContext.getBean("tenantService")); bootstrap.bootstrap(); // retrieve policy component this.policyComponent = (PolicyComponent)applicationContext.getBean("policyComponent"); this.behaviourFilter = (BehaviourFilter) applicationContext.getBean("policyBehaviourFilter"); this.trxService = (TransactionService) applicationContext.getBean("transactionComponent"); this.nodeService = (NodeService) applicationContext.getBean("nodeService"); this.nodeLocatorService = (NodeLocatorService) applicationContext.getBean("nodeLocatorService"); this.authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent"); this.authenticationComponent.setSystemUserAsCurrentUser(); // Register Policy if (sideEffectDelegate == null) { sideEffectDelegate = policyComponent.registerClassPolicy(SideEffectTestPolicy.class); // Bind Behaviour to side effect policy QName policyName = QName.createQName(TEST_NAMESPACE, "sideEffect"); Behaviour baseBehaviour = new JavaBehaviour(this, "sideEffectTest", NotificationFrequency.TRANSACTION_COMMIT); this.policyComponent.bindClassBehaviour(policyName, BASE_TYPE, baseBehaviour); } this.companyHome = nodeLocatorService.getNode(CompanyHomeNodeLocator.NAME, null, null); createAndEnableBehaviours(); } private void createAndEnableBehaviours() { aTypeBehavior = new TestOnCreateNodePolicy(); bTypeBehavior = new TestOnCreateNodePolicy(); cTypeBehavior = new TestOnCreateNodePolicy(); // bind custom behavior for super type policyComponent.bindClassBehaviour(OnCreateNodePolicy.QNAME, A_TYPE, new JavaBehaviour(aTypeBehavior, "onCreateNode")); // bind custom behavior for "middle" type policyComponent.bindClassBehaviour(OnCreateNodePolicy.QNAME, B_TYPE, new JavaBehaviour(bTypeBehavior, "onCreateNode")); // bind custom behavior for sub type policyComponent.bindClassBehaviour(OnCreateNodePolicy.QNAME, C_TYPE, new JavaBehaviour(cTypeBehavior, "onCreateNode")); } @Override protected void tearDown() throws Exception { authenticationComponent.clearCurrentSecurityContext(); } public void testStartTransactionPolicy() throws Exception { ClassPolicyDelegate startDelegate = policyComponent.registerClassPolicy(StartTestPolicy.class); // Register Policy QName policyName = QName.createQName(TEST_NAMESPACE, "start"); PolicyDefinition definition = policyComponent.getRegisteredPolicy(PolicyType.Class, policyName); assertNotNull(definition); Arg arg0 = definition.getArgument(0); assertEquals(Arg.KEY, arg0); Arg arg1 = definition.getArgument(1); assertEquals(Arg.KEY, arg1); Arg arg2 = definition.getArgument(2); assertEquals(Arg.START_VALUE, arg2); Arg arg3 = definition.getArgument(3); assertEquals(Arg.END_VALUE, arg3); // Bind Behaviour Behaviour baseBehaviour = new JavaBehaviour(this, "startTransactionTest", NotificationFrequency.FIRST_EVENT); policyComponent.bindClassBehaviour(policyName, BASE_TYPE, baseBehaviour); // Invoke Behaviour UserTransaction userTransaction1 = trxService.getUserTransaction(); try { userTransaction1.begin(); List results = new ArrayList(); StartTestPolicy basePolicy = startDelegate.get(BASE_TYPE); String baseResult1 = basePolicy.start("1", "2", "value1a", "value2a", false, results); TestResult result1 = new TestResult("startTransactionTest", "1", "2", "value1a", "value2a"); assertEquals(result1.toString(), baseResult1); assertEquals(1, results.size()); assertEquals(result1, results.get(0)); String baseResult2 = basePolicy.start("2", "1", "value1b", "value2b", false, results); TestResult result2 = new TestResult("startTransactionTest", "2", "1", "value1b", "value2b"); assertEquals(result2.toString(), baseResult2); assertEquals(2, results.size()); assertEquals(result2, results.get(1)); String baseResult3 = basePolicy.start("1", "2", "value1c", "value2c", false, results); assertEquals(result1.toString(), baseResult3); assertEquals(2, results.size()); userTransaction1.commit(); assertEquals(2, results.size()); assertEquals(result1, results.get(0)); assertEquals(result2, results.get(1)); } catch(Exception e) { try { userTransaction1.rollback(); } catch (IllegalStateException ee) {} throw e; } // Invoke Behaviour UserTransaction userTransaction2 = trxService.getUserTransaction(); try { userTransaction2.begin(); List results = new ArrayList(); StartTestPolicy basePolicy = startDelegate.get(BASE_TYPE); String baseResult1 = basePolicy.start("1", "2", "value1a", "value2a", true, results); TestResult result1 = new TestResult("startTransactionTest", "1", "2", "value1a", "value2a"); assertEquals(result1.toString(), baseResult1); assertEquals(1, results.size()); assertEquals(result1, results.get(0)); String baseResult2 = basePolicy.start("2", "1", "value1b", "value2b", true, results); TestResult result2 = new TestResult("startTransactionTest", "2", "1", "value1b", "value2b"); assertEquals(result2.toString(), baseResult2); assertEquals(2, results.size()); assertEquals(result2, results.get(1)); String baseResult3 = basePolicy.start("1", "2", "value1c", "value2c", true, results); assertEquals(result1.toString(), baseResult3); assertEquals(2, results.size()); TestResult result3 = new TestResult("sideEffectTest", "1", "2", "value1a", "value2a"); TestResult result4 = new TestResult("sideEffectTest", "2", "1", "value1b", "value2b"); userTransaction2.commit(); assertEquals(4, results.size()); assertEquals(result1, results.get(0)); assertEquals(result2, results.get(1)); assertEquals(result3, results.get(2)); assertEquals(result4, results.get(3)); } catch(Exception e) { try { userTransaction2.rollback(); } catch (IllegalStateException ee) {} throw e; } } public void testEndTransactionPolicy() throws Exception { ClassPolicyDelegate endDelegate = policyComponent.registerClassPolicy(EndTestPolicy.class); QName policyName = QName.createQName(TEST_NAMESPACE, "end"); PolicyDefinition definition = policyComponent.getRegisteredPolicy(PolicyType.Class, policyName); assertNotNull(definition); Arg arg0 = definition.getArgument(0); assertEquals(Arg.KEY, arg0); Arg arg1 = definition.getArgument(1); assertEquals(Arg.KEY, arg1); Arg arg2 = definition.getArgument(2); assertEquals(Arg.START_VALUE, arg2); Arg arg3 = definition.getArgument(3); assertEquals(Arg.END_VALUE, arg3); // Bind Behaviour Behaviour baseBehaviour = new JavaBehaviour(this, "endTransactionTest", NotificationFrequency.TRANSACTION_COMMIT); policyComponent.bindClassBehaviour(policyName, BASE_TYPE, baseBehaviour); UserTransaction userTransaction1 = trxService.getUserTransaction(); try { userTransaction1.begin(); List results = new ArrayList(); // Invoke Behaviour EndTestPolicy basePolicy = endDelegate.get(BASE_TYPE); String baseResult1 = basePolicy.end("1", "2", "value1a", "value2a", false, results); assertEquals(null, baseResult1); assertEquals(0, results.size()); String baseResult2 = basePolicy.end("2", "1", "value1b", "value2b", false, results); assertEquals(null, baseResult2); assertEquals(0, results.size()); String baseResult3 = basePolicy.end("1", "2", "value1a", "value2c", false, results); assertEquals(null, baseResult3); assertEquals(0, results.size()); TestResult result1 = new TestResult("endTransactionTest", "1", "2", "value1a", "value2c"); TestResult result2 = new TestResult("endTransactionTest", "2", "1", "value1b", "value2b"); userTransaction1.commit(); assertEquals(2, results.size()); assertEquals(result1, results.get(0)); assertEquals(result2, results.get(1)); } catch(Exception e) { try { userTransaction1.rollback(); } catch (IllegalStateException ee) {} throw e; } UserTransaction userTransaction2 = trxService.getUserTransaction(); try { userTransaction2.begin(); List results = new ArrayList(); // Invoke Behaviour EndTestPolicy basePolicy = endDelegate.get(BASE_TYPE); String baseResult1 = basePolicy.end("1", "2", "value1a", "value2a", true, results); assertEquals(null, baseResult1); assertEquals(0, results.size()); String baseResult2 = basePolicy.end("2", "1", "value1b", "value2b", true, results); assertEquals(null, baseResult2); assertEquals(0, results.size()); String baseResult3 = basePolicy.end("1", "2", "value1a", "value2c", true, results); assertEquals(null, baseResult3); assertEquals(0, results.size()); TestResult result1 = new TestResult("endTransactionTest", "1", "2", "value1a", "value2c"); TestResult result2 = new TestResult("endTransactionTest", "2", "1", "value1b", "value2b"); TestResult result3 = new TestResult("sideEffectTest", "1", "2", "value1a", "value2c"); TestResult result4 = new TestResult("sideEffectTest", "2", "1", "value1b", "value2b"); userTransaction2.commit(); assertEquals(4, results.size()); assertEquals(result1, results.get(0)); assertEquals(result2, results.get(1)); assertEquals(result3, results.get(2)); assertEquals(result4, results.get(3)); } catch(Exception e) { 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; } } public void behaviourHierarchyTestWork(QName createDocType, ClassFilter... disableTypes) throws Exception { UserTransaction transaction = trxService.getUserTransaction(); try { transaction.begin(); disableBehaviours(disableTypes); try { createDocOfType(createDocType); } finally { enableBehaviours(disableTypes); } transaction.commit(); } catch(Exception e) { try { transaction.rollback(); } catch (IllegalStateException ee) {} throw e; } } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyEnableAll1() throws Exception { behaviourHierarchyTestWork(A_TYPE); assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyEnableAll2() throws Exception { behaviourHierarchyTestWork(B_TYPE); assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(1, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyEnableAll3() throws Exception { behaviourHierarchyTestWork(C_TYPE); assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(1, bTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(1, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableAllUpHierarchy1() throws Exception { behaviourHierarchyTestWork( A_TYPE, new ClassFilter(A_TYPE, false), new ClassFilter(B_TYPE, false), new ClassFilter(C_TYPE, false) ); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableAllUpHierarchy2() throws Exception { behaviourHierarchyTestWork( B_TYPE, new ClassFilter(A_TYPE, false), new ClassFilter(B_TYPE, false), new ClassFilter(C_TYPE, false) ); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableAllUpHierarchy3() throws Exception { behaviourHierarchyTestWork( C_TYPE, new ClassFilter(A_TYPE, false), new ClassFilter(B_TYPE, false), new ClassFilter(C_TYPE, false) ); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableAllDownHierarchy1() throws Exception { behaviourHierarchyTestWork( A_TYPE, new ClassFilter(A_TYPE, true), new ClassFilter(B_TYPE, true), new ClassFilter(C_TYPE, true) ); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableAllDownHierarchy2() throws Exception { behaviourHierarchyTestWork( B_TYPE, new ClassFilter(A_TYPE, true), new ClassFilter(B_TYPE, true), new ClassFilter(C_TYPE, true) ); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableAllDownHierarchy3() throws Exception { behaviourHierarchyTestWork( C_TYPE, new ClassFilter(A_TYPE, true), new ClassFilter(B_TYPE, true), new ClassFilter(C_TYPE, true) ); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableSuper1() throws Exception { behaviourHierarchyTestWork(A_TYPE, new ClassFilter(A_TYPE, false)); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableSuper2() throws Exception { behaviourHierarchyTestWork(B_TYPE, new ClassFilter(A_TYPE, false)); assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(1, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableSuper3() throws Exception { behaviourHierarchyTestWork(C_TYPE, new ClassFilter(A_TYPE, false)); assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(1, bTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(1, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testBehaviourHierarchyDisableSuper4() throws Exception { behaviourHierarchyTestWork(A_TYPE, new ClassFilter(A_TYPE, true)); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testBehaviourHierarchyDisableSuper5() throws Exception { behaviourHierarchyTestWork(B_TYPE, new ClassFilter(A_TYPE, true)); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testBehaviourHierarchyDisableSuper6() throws Exception { behaviourHierarchyTestWork(C_TYPE, new ClassFilter(A_TYPE, true)); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableMiddle1() throws Exception { behaviourHierarchyTestWork(A_TYPE, new ClassFilter(B_TYPE, false)); assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableMiddle2() throws Exception { behaviourHierarchyTestWork(B_TYPE, new ClassFilter(B_TYPE, false)); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableMiddle3() throws Exception { behaviourHierarchyTestWork(C_TYPE, new ClassFilter(B_TYPE, false)); assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(1, bTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(1, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testBehaviourHierarchyDisableMiddle4() throws Exception { behaviourHierarchyTestWork(A_TYPE, new ClassFilter(B_TYPE, true)); assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testBehaviourHierarchyDisableMiddle5() throws Exception { behaviourHierarchyTestWork(B_TYPE, new ClassFilter(B_TYPE, true)); assertFalse("Behavior should notbe executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior not should be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testBehaviourHierarchyDisableMiddle6() throws Exception { behaviourHierarchyTestWork(C_TYPE, new ClassFilter(B_TYPE, true)); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableSub1() throws Exception { behaviourHierarchyTestWork(A_TYPE, new ClassFilter(C_TYPE, false)); assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableSub2() throws Exception { behaviourHierarchyTestWork(B_TYPE, new ClassFilter(C_TYPE, false)); assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(1, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 * @throws Exception */ public void testBehaviourHierarchyDisableSub3() throws Exception { behaviourHierarchyTestWork(C_TYPE, new ClassFilter(C_TYPE, false)); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testBehaviourHierarchyDisableSub4() throws Exception { behaviourHierarchyTestWork(A_TYPE, new ClassFilter(C_TYPE, true)); assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testBehaviourHierarchyDisableSub5() throws Exception { behaviourHierarchyTestWork(B_TYPE, new ClassFilter(C_TYPE, true)); assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(1, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testBehaviourHierarchyDisableSub6() throws Exception { behaviourHierarchyTestWork(C_TYPE, new ClassFilter(C_TYPE, true)); assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testIsEnabled1() throws Exception { UserTransaction transaction = trxService.getUserTransaction(); try { transaction.begin(); disableBehaviours(new ClassFilter(B_TYPE, true)); try { assertEquals("Incorrect behaviour state: global: ", true, behaviourFilter.isEnabled()); // A_TYPE assertEquals("Incorrect behaviour state: class: ", true, behaviourFilter.isEnabled(A_TYPE)); assertEquals("Incorrect behaviour state: classAndInstance", true, behaviourFilter.isEnabled(companyHome, A_TYPE)); assertEquals("Incorrect behaviour state: instance", true, behaviourFilter.isEnabled(companyHome)); // B_TYPE assertEquals("Incorrect behaviour state: class: ", false, behaviourFilter.isEnabled(B_TYPE)); assertEquals("Incorrect behaviour state: classAndInstance", false, behaviourFilter.isEnabled(companyHome, B_TYPE)); assertEquals("Incorrect behaviour state: instance", true, behaviourFilter.isEnabled(companyHome)); // C_TYPE assertEquals("Incorrect behaviour state: class: ", false, behaviourFilter.isEnabled(C_TYPE)); assertEquals("Incorrect behaviour state: classAndInstance", false, behaviourFilter.isEnabled(companyHome, C_TYPE)); assertEquals("Incorrect behaviour state: instance", true, behaviourFilter.isEnabled(companyHome)); } finally { behaviourFilter.enableBehaviour(B_TYPE); } transaction.commit(); } catch(Exception e) { try { transaction.rollback(); } catch (IllegalStateException ee) {} throw e; } } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testIsEnabled2() throws Exception { UserTransaction transaction = trxService.getUserTransaction(); try { transaction.begin(); disableBehaviours(new ClassFilter(B_TYPE, false)); try { assertEquals("Incorrect behaviour state: global: ", true, behaviourFilter.isEnabled()); // A_TYPE assertEquals("Incorrect behaviour state: class: ", true, behaviourFilter.isEnabled(A_TYPE)); assertEquals("Incorrect behaviour state: classAndInstance", true, behaviourFilter.isEnabled(companyHome, A_TYPE)); assertEquals("Incorrect behaviour state: instance", true, behaviourFilter.isEnabled(companyHome)); // B_TYPE assertEquals("Incorrect behaviour state: class: ", false, behaviourFilter.isEnabled(B_TYPE)); assertEquals("Incorrect behaviour state: classAndInstance", false, behaviourFilter.isEnabled(companyHome, B_TYPE)); assertEquals("Incorrect behaviour state: instance", true, behaviourFilter.isEnabled(companyHome)); // C_TYPE assertEquals("Incorrect behaviour state: class: ", true, behaviourFilter.isEnabled(C_TYPE)); assertEquals("Incorrect behaviour state: classAndInstance", true, behaviourFilter.isEnabled(companyHome, C_TYPE)); assertEquals("Incorrect behaviour state: instance", true, behaviourFilter.isEnabled(companyHome)); } finally { behaviourFilter.enableBehaviour(B_TYPE); } transaction.commit(); } catch(Exception e) { try { transaction.rollback(); } catch (IllegalStateException ee) {} throw e; } } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testBehaviourHierarchySequence1() throws Exception { UserTransaction transaction = trxService.getUserTransaction(); try { transaction.begin(); disableBehaviours(new ClassFilter(A_TYPE, true), new ClassFilter(B_TYPE, true)); behaviourFilter.enableBehaviour(B_TYPE); // Should be still disabled checkBehaviour(B_TYPE, companyHome, true, false, false, true); try { createDocOfType(C_TYPE); } finally { enableBehaviours(new ClassFilter(A_TYPE, true), new ClassFilter(B_TYPE, true)); } transaction.commit(); } catch(Exception e) { try { transaction.rollback(); } catch (IllegalStateException ee) {} throw e; } assertFalse("Behavior should not be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(0, aTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(0, bTypeBehavior.getExecutionCount()); assertFalse("Behavior should not be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(0, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testBehaviourHierarchySequence2() throws Exception { UserTransaction transaction = trxService.getUserTransaction(); try { transaction.begin(); disableBehaviours(new ClassFilter(A_TYPE, false), new ClassFilter(B_TYPE, true)); behaviourFilter.enableBehaviour(B_TYPE); assertEquals("Incorrect behaviour state: class: ", true, behaviourFilter.isEnabled(B_TYPE)); assertEquals("Incorrect behaviour state: classAndInstance", true, behaviourFilter.isEnabled(companyHome, B_TYPE)); assertEquals("Incorrect behaviour state: instance", true, behaviourFilter.isEnabled(companyHome)); try { createDocOfType(C_TYPE); } finally { enableBehaviours(new ClassFilter(A_TYPE, true), new ClassFilter(B_TYPE, true)); } transaction.commit(); } catch(Exception e) { try { transaction.rollback(); } catch (IllegalStateException ee) {} throw e; } assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(1, bTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(1, cTypeBehavior.getExecutionCount()); } /** * Test for MNT-13836 (new API) * @throws Exception */ public void testBehaviourHierarchySequence3() throws Exception { UserTransaction transaction = trxService.getUserTransaction(); try { transaction.begin(); disableBehaviours(new ClassFilter(A_TYPE, false), new ClassFilter(B_TYPE, false)); try { createDocOfType(C_TYPE); } finally { enableBehaviours(new ClassFilter(A_TYPE, true), new ClassFilter(B_TYPE, true)); } transaction.commit(); } catch(Exception e) { try { transaction.rollback(); } catch (IllegalStateException ee) {} throw e; } assertTrue("Behavior should be executed for a_type.", aTypeBehavior.isExecuted()); assertEquals(1, aTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for b_type.", bTypeBehavior.isExecuted()); assertEquals(1, bTypeBehavior.getExecutionCount()); assertTrue("Behavior should be executed for c_type.", cTypeBehavior.isExecuted()); assertEquals(1, cTypeBehavior.getExecutionCount()); } private void disableBehaviours(ClassFilter... classFilters) { for(int i = 0; i < classFilters.length; i++) { behaviourFilter.disableBehaviour( classFilters[i].getClassName(), classFilters[i].isDisableSubClasses() ); // check that behavior is disabled correctly checkBehaviour(classFilters[i].getClassName(), companyHome, true, false, false, true); } } private void enableBehaviours(ClassFilter... types) { for(int i = 0; i < types.length; i++) { behaviourFilter.enableBehaviour(types[i].getClassName()); } for(int i = 0; i < types.length; i++) { checkBehaviour(types[i].getClassName(), companyHome, true, true, true, true); } } private void createDocOfType(QName type) { final String name = "Test (" + System.currentTimeMillis() + ").docx"; final Map contentProps = new HashMap(); contentProps.put(ContentModel.PROP_NAME, name); // create node of child type nodeService.createNode(companyHome, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_PREFIX, name), type, contentProps); } /** * @param className the class to check * @param nodeRef the node instance to check * @param globalEnabled true if the global filter should be enabled * @param classEnabled true if the class should be enabled * @param classInstanceEnabled true if the class and instance should be enabled * @param instanceEnabled true 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 // public String startTransactionTest(String key1, String key2, String arg1, String arg2, boolean sideEffect, List results) { TestResult result = new TestResult("startTransactionTest", key1, key2, arg1, arg2); results.add(result); if (sideEffect) { SideEffectTestPolicy policy = sideEffectDelegate.get(BASE_TYPE); policy.sideEffect(key1, key2, arg1, arg2, results); } return result.toString(); } public String endTransactionTest(String key1, String key2, String arg1, String arg2, boolean sideEffect, List results) { TestResult result = new TestResult("endTransactionTest", key1, key2, arg1, arg2); results.add(result); if (sideEffect) { SideEffectTestPolicy policy = sideEffectDelegate.get(BASE_TYPE); policy.sideEffect(key1, key2, arg1, arg2, results); } return result.toString(); } public String sideEffectTest(String key1, String key2, String arg1, String arg2, List results) { TestResult result = new TestResult("sideEffectTest", key1, key2, arg1, arg2); results.add(result); return result.toString(); } // // Policy Definitions // public interface StartTestPolicy extends ClassPolicy { public String start(String key1, String key2, String arg1, String arg2, boolean sideEffect, List results); static String NAMESPACE = TEST_NAMESPACE; static Arg ARG_0 = Arg.KEY; static Arg ARG_1 = Arg.KEY; static Arg ARG_2 = Arg.START_VALUE; static Arg ARG_3 = Arg.END_VALUE; } public interface EndTestPolicy extends ClassPolicy { public String end(String key1, String key2, String arg1, String arg2, boolean sideEffect, List results); static String NAMESPACE = TEST_NAMESPACE; static Arg ARG_0 = Arg.KEY; static Arg ARG_1 = Arg.KEY; static Arg ARG_2 = Arg.START_VALUE; static Arg ARG_3 = Arg.END_VALUE; } public interface SideEffectTestPolicy extends ClassPolicy { public String sideEffect(String key1, String key2, String arg1, String arg2, List resultTest); static String NAMESPACE = TEST_NAMESPACE; static Arg ARG_0 = Arg.KEY; static Arg ARG_1 = Arg.KEY; } /** * Result of Policy Invocation */ private class TestResult { private String trxId; private String behaviour; private String key1; private String key2; private String arg1; private String arg2; /** * Construct * * @param behaviour String * @param key1 String * @param key2 String * @param arg1 String * @param arg2 String */ public TestResult(String behaviour, String key1, String key2, String arg1, String arg2) { this.trxId = AlfrescoTransactionSupport.getTransactionId(); this.behaviour = behaviour; this.key1 = key1; this.key2 = key2; this.arg1 = arg1; this.arg2 = arg2; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof TestResult) { TestResult that = (TestResult) obj; return (this.trxId.equals(that.trxId) && this.behaviour.equals(that.behaviour) && this.key1.equals(that.key1) && this.key2.equals(that.key2) && this.arg1.equals(that.arg1) && this.arg2.equals(that.arg2)); } else { return false; } } @Override public String toString() { return "trxId=" + trxId + ", behaviour=" + behaviour + ", key1=" + key1 + ", key2=" + key2 + ", arg1=" + arg1 + ", arg2=" + arg2; } } private class TestOnCreateNodePolicy implements OnCreateNodePolicy { private boolean executed; private int executionCount; @Override public void onCreateNode(ChildAssociationRef childAssocRef) { executed = true; executionCount++; } public boolean isExecuted() { return executed; } public int getExecutionCount() { return executionCount; } } }