From 75730e988f2c6e1f536d808c41079ef8cf4a5bc3 Mon Sep 17 00:00:00 2001 From: Alan Davis Date: Wed, 12 Feb 2014 00:45:50 +0000 Subject: [PATCH] Merged HEAD-BUG-FIX (4.3/Cloud) to HEAD (4.3/Cloud) 59033: Merged V4.2-BUG-FIX (4.2.1) to HEAD-BUG-FIX (Cloud/4.3) 58999: Merged V4.1-BUG-FIX (4.1.8) to V4.2-BUG-FIX (4.2.1) 58913: Fix MT ContentStore so that it cannot return a null store - It was dependent, for some reason, on a cluster-aware cache that would be prone to nulling but the code just assumed that if it tried to set the value a few times it would stick. - Fixed transaction demarcation so that a transaction is always present when using the store. This is not ideal but it is inherently a repo-aware component and therefore needs it - MNT-9806: Prevent post-transaction handlers from rendering threads unusable - MNT-10096: MT: AbstractTenantRoutingContentStore can return null list of stores Merged from DEV/DEREK/MNT-9806 r58833 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@62077 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/mt/mt-base-context.xml | 5 +- ...AbstractTenantRoutingContentStoreTest.java | 175 ++++++++++++++++++ 2 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 source/test-java/org/alfresco/repo/tenant/AbstractTenantRoutingContentStoreTest.java diff --git a/config/alfresco/mt/mt-base-context.xml b/config/alfresco/mt/mt-base-context.xml index 7fdaec8613..fb3b05ea2a 100644 --- a/config/alfresco/mt/mt-base-context.xml +++ b/config/alfresco/mt/mt-base-context.xml @@ -16,9 +16,6 @@ - @@ -46,7 +43,7 @@ - + diff --git a/source/test-java/org/alfresco/repo/tenant/AbstractTenantRoutingContentStoreTest.java b/source/test-java/org/alfresco/repo/tenant/AbstractTenantRoutingContentStoreTest.java new file mode 100644 index 0000000000..5299d3c49e --- /dev/null +++ b/source/test-java/org/alfresco/repo/tenant/AbstractTenantRoutingContentStoreTest.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.tenant; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.ContentStore; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.transaction.AlfrescoTransactionSupport; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.repo.transaction.TransactionListenerAdapter; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ApplicationContextHelper; +import org.springframework.context.ApplicationContext; + +/** + * Test checking the behaviour of the MT {@link ContentStore} routing + * + * @author Alfresco + * @since 4.2.1 + */ +public class AbstractTenantRoutingContentStoreTest extends TestCase +{ + private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(); + + private ContentService contentService; + private ServiceRegistry serviceRegistry; + private AbstractTenantRoutingContentStore fileContentStore; + private boolean isNullEntry = false; + + @Override + public void setUp() throws Exception + { + AuthenticationUtil.setRunAsUserSystem(); + + serviceRegistry = (ServiceRegistry) ctx.getBean("ServiceRegistry"); + contentService = serviceRegistry.getContentService(); + fileContentStore = (AbstractTenantRoutingContentStore) ctx.getBean("fileContentStore"); + } + + public void testGetAllStores() throws Exception + { + final RetryingTransactionCallback txnWork = new RetryingTransactionCallback() + { + public Boolean execute() throws Exception + { + // The listener + final TestAfterRollbackTxnListener listener = new TestAfterRollbackTxnListener(); + AlfrescoTransactionSupport.bindListener(listener); + + NodeRef content = createContent(serviceRegistry); + + ContentWriter writer = contentService.getWriter(content, ContentModel.PROP_CONTENT, true); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + writer.putContent("The quick brown fox jumps over the lazy dog"); + + throw new AlfrescoRuntimeException("Some error that causes RollBack. The transaction will be closed"); + } + }; + + try + { + serviceRegistry.getTransactionService().getRetryingTransactionHelper().doInTransaction(txnWork, false, false); + } + catch (AlfrescoRuntimeException e) + { + // Expected + } + + assertFalse("getAllStores method returned the list with null entry", isNullEntry); + } + + // helper methods and listener + private void checkStores(List stores) + { + // check that list is not empty + assertEquals(false, stores.isEmpty()); + + // check for null entry + for (ContentStore store : stores) + { + if (store == null) + { + isNullEntry = true; + } + } + } + + private NodeRef createContent(ServiceRegistry serviceRegistry) throws Exception + { + AuthenticationService authenticationService = serviceRegistry.getAuthenticationService(); + authenticationService.authenticate("admin", "admin".toCharArray()); + SearchService searchService = serviceRegistry.getSearchService(); + StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore"); + + try + { + ResultSet resultSet = searchService.query(storeRef, SearchService.LANGUAGE_LUCENE, "PATH:\"/app:company_home\""); + NodeRef companyHome = resultSet.getNodeRef(0); + + serviceRegistry.getFileFolderService().create(companyHome, "Test", ContentModel.TYPE_FOLDER); + resultSet.close(); + } + catch (Exception e) + { + } + + ResultSet resultSet = searchService.query(storeRef, SearchService.LANGUAGE_LUCENE, "PATH:\"/app:company_home/cm:Test\""); + NodeRef node = resultSet.getNodeRef(0); + resultSet.close(); + + // assign name + String name = "TestContent(" + Thread.currentThread().getName() + " " + System.currentTimeMillis() + ")"; + Map contentProps = new HashMap(); + contentProps.put(ContentModel.PROP_NAME, name); + + // create content node + NodeService nodeService = serviceRegistry.getNodeService(); + ChildAssociationRef association = nodeService.createNode(node, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_PREFIX, name), + ContentModel.TYPE_CONTENT, contentProps); + NodeRef content = association.getChildRef(); + + // add titled aspect (for Web Client display) + Map titledProps = new HashMap(); + titledProps.put(ContentModel.PROP_TITLE, name); + titledProps.put(ContentModel.PROP_DESCRIPTION, name); + nodeService.addAspect(content, ContentModel.ASPECT_TITLED, titledProps); + + return content; + } + + private class TestAfterRollbackTxnListener extends TransactionListenerAdapter + { + @Override + public void afterRollback() + { + checkStores(fileContentStore.getAllStores()); + } + } +}