From 2c97a0e38bf95e6d995a6e517dce248b175b25d3 Mon Sep 17 00:00:00 2001 From: Jan Vonka Date: Thu, 5 Aug 2010 11:15:32 +0000 Subject: [PATCH] RepoAdminServiceImplTest: test/build fixes git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21633 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../repo/admin/RepoAdminServiceImpl.java | 97 +++++++++++++------ .../repo/admin/RepoAdminServiceImplTest.java | 84 +++++++++++----- 2 files changed, 131 insertions(+), 50 deletions(-) diff --git a/source/java/org/alfresco/repo/admin/RepoAdminServiceImpl.java b/source/java/org/alfresco/repo/admin/RepoAdminServiceImpl.java index d810e4648d..c365af6f85 100644 --- a/source/java/org/alfresco/repo/admin/RepoAdminServiceImpl.java +++ b/source/java/org/alfresco/repo/admin/RepoAdminServiceImpl.java @@ -42,17 +42,20 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; 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.SearchService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; -import org.springframework.extensions.surf.util.ParameterCheck; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.dao.ConcurrencyFailureException; +import org.springframework.extensions.surf.util.ParameterCheck; /** * Repository Admin Service Implementation. @@ -153,18 +156,26 @@ public class RepoAdminServiceImpl implements RepoAdminService { String modelFileName = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); String repoVersion = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_VERSION_LABEL); - - String modelName = null; - - ContentReader cr = contentService.getReader(nodeRef, ContentModel.TYPE_CONTENT); - InputStream is = cr.getContentInputStream(); try { - M2Model model = M2Model.createModel(is); - is.close(); + String modelName = null; - modelName = model.getName(); + ContentReader cr = contentService.getReader(nodeRef, ContentModel.TYPE_CONTENT); + + if (cr != null) + { + InputStream is = cr.getContentInputStream(); + try + { + M2Model model = M2Model.createModel(is); + modelName = model.getName(); + } + finally + { + is.close(); + } + } // check against models loaded in dictionary and give warning if not found if (dictionaryModels.contains(modelName)) @@ -195,13 +206,13 @@ public class RepoAdminServiceImpl implements RepoAdminService { try { - // Check that all the passed values are not null + // Check that all the passed values are not null ParameterCheck.mandatory("ModelStream", modelStream); ParameterCheck.mandatoryString("ModelFileName", modelFileName); Map contentProps = new HashMap(); contentProps.put(ContentModel.PROP_NAME, modelFileName); - + StoreRef storeRef = repoModelsLocation.getStoreRef(); NodeRef rootNode = nodeService.getRootNode(storeRef); @@ -216,7 +227,7 @@ public class RepoAdminServiceImpl implements RepoAdminService // unexpected: should not find multiple nodes with same name throw new AlfrescoRuntimeException("Found multiple custom models location " + repoModelsLocation.getPath()); } - + NodeRef customModelsSpaceNodeRef = nodeRefs.get(0); nodeRefs = searchService.selectNodes(customModelsSpaceNodeRef, "*[@cm:name='"+modelFileName+"' and "+defaultSubtypeOfDictionaryModel+"]", null, namespaceService, false); @@ -233,14 +244,24 @@ public class RepoAdminServiceImpl implements RepoAdminService { // deploy new model to the repository - // note: dictionary model type has associated policies that will be invoked - ChildAssociationRef association = nodeService.createNode(customModelsSpaceNodeRef, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, modelFileName), - ContentModel.TYPE_DICTIONARY_MODEL, - contentProps); // also invokes policies for DictionaryModelType - e.g. onUpdateProperties - - modelNodeRef = association.getChildRef(); + try + { + // note: dictionary model type has associated policies that will be invoked + ChildAssociationRef association = nodeService.createNode(customModelsSpaceNodeRef, + ContentModel.ASSOC_CONTAINS, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, modelFileName), + ContentModel.TYPE_DICTIONARY_MODEL, + contentProps); // also invokes policies for DictionaryModelType - e.g. onUpdateProperties + + modelNodeRef = association.getChildRef(); + } + catch (DuplicateChildNodeNameException dcnne) + { + String msg = "Model already exists: "+modelFileName+" - "+dcnne; + logger.warn(msg); + // for now, assume concurrency failure + throw new ConcurrencyFailureException(msg); + } // add titled aspect (for Web Client display) Map titledProps = new HashMap(); @@ -409,19 +430,30 @@ public class RepoAdminServiceImpl implements RepoAdminService */ public QName undeployModel(String modelFileName) { - // Check that all the passed values are not null + // Check that all the passed values are not null ParameterCheck.mandatory("modelFileName", modelFileName); QName modelQName = null; try - { + { // find model in repository - StoreRef storeRef = repoModelsLocation.getStoreRef(); + StoreRef storeRef = repoModelsLocation.getStoreRef(); NodeRef rootNode = nodeService.getRootNode(storeRef); - - List nodeRefs = searchService.selectNodes(rootNode, repoModelsLocation.getPath()+"//.[@cm:name='"+modelFileName+"' and "+defaultSubtypeOfDictionaryModel+"]", null, namespaceService, false); + + List nodeRefs = null; + try + { + nodeRefs = searchService.selectNodes(rootNode, repoModelsLocation.getPath()+"//.[@cm:name='"+modelFileName+"' and "+defaultSubtypeOfDictionaryModel+"]", null, namespaceService, false); + } + catch (InvalidNodeRefException inre) + { + String msg = "Model no longer exists: "+modelFileName+" - "+inre; + logger.warn(msg); + // for now, assume concurrency failure + throw new ConcurrencyFailureException(msg); + } if (nodeRefs.size() == 0) { @@ -467,14 +499,25 @@ public class RepoAdminServiceImpl implements RepoAdminService // permanently remove model from repository nodeService.addAspect(modelNodeRef, ContentModel.ASPECT_TEMPORARY, null); - nodeService.deleteNode(modelNodeRef); + + try + { + nodeService.deleteNode(modelNodeRef); + } + catch (DictionaryException de) + { + String msg = "Model undeployment failed: "+modelFileName+" - "+de; + logger.warn(msg); + // for now, assume concurrency failure + throw new ConcurrencyFailureException(msg); + } // note: deleted model will be unloaded as part of DictionaryModelType.beforeCommit() } catch (Throwable e) { throw new AlfrescoRuntimeException("Model undeployment failed ", e); - } + } return modelQName; } diff --git a/source/java/org/alfresco/repo/admin/RepoAdminServiceImplTest.java b/source/java/org/alfresco/repo/admin/RepoAdminServiceImplTest.java index f9f4a7ec50..8e51c586c0 100644 --- a/source/java/org/alfresco/repo/admin/RepoAdminServiceImplTest.java +++ b/source/java/org/alfresco/repo/admin/RepoAdminServiceImplTest.java @@ -40,6 +40,7 @@ import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.service.cmr.admin.RepoAdminService; import org.alfresco.service.cmr.dictionary.ClassDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; @@ -51,6 +52,7 @@ import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.ApplicationContextHelper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -69,6 +71,7 @@ public class RepoAdminServiceImplTest extends TestCase private RepoAdminService repoAdminService; private DictionaryService dictionaryService; + private TransactionService transactionService; private NodeService nodeService; private ContentService contentService; private SearchService searchService; @@ -118,6 +121,7 @@ public class RepoAdminServiceImplTest extends TestCase repoAdminService = (RepoAdminService) ctx.getBean("RepoAdminService"); dictionaryService = (DictionaryService) ctx.getBean("DictionaryService"); + transactionService = (TransactionService) ctx.getBean("TransactionService"); nodeService = (NodeService) ctx.getBean("NodeService"); contentService = (ContentService) ctx.getBean("ContentService"); searchService = (SearchService) ctx.getBean("SearchService"); @@ -137,6 +141,21 @@ public class RepoAdminServiceImplTest extends TestCase // NOOP } + public void xtestRepeat() throws Exception + { + int cnt = 10; + + for (int i = 1; i <= cnt; i++) + { + System.out.println("Itr: "+i+" out of "+cnt); + + testSimpleDynamicModelViaNodeService(); + testSimpleDynamicModelViaRepoAdminService(); + testConcurrentDynamicModelCreate(); + testConcurrentDynamicModelDelete(); + } + } + // // Test custom model management // @@ -250,7 +269,7 @@ public class RepoAdminServiceImplTest extends TestCase // delete model nodeService.deleteNode(model1); - + assertEquals(defaultModelCnt, dictionaryService.getAllModels().size()); assertNull(dictionaryService.getClass(typeName)); @@ -258,7 +277,6 @@ public class RepoAdminServiceImplTest extends TestCase // restore model nodeService.restoreNode(archiveModel1, null, null, null); - assertEquals(defaultModelCnt+1, dictionaryService.getAllModels().size()); assertNotNull(dictionaryService.getClass(typeName)); @@ -477,34 +495,46 @@ public class RepoAdminServiceImplTest extends TestCase public void testConcurrentDynamicModelCreate() throws Exception { - final int n = 5; + final int n = 2; undeployModels(n); int deployedModelCount = repoAdminService.getModels().size(); - logger.info("Existing deployed custom model count: "+deployedModelCount); + logger.info("Before deploy: deployed custom model count: "+deployedModelCount); int dictModelCount = getModelCount(); - logger.info("Existing dictionary model count: "+dictModelCount); + logger.info("Before deploy: dictionary model count: "+dictModelCount); // concurrently deploy N models runConcurrentOps(n, 1); - assertEquals(deployedModelCount+n, repoAdminService.getModels().size()); + int newDeployedModelCount = repoAdminService.getModels().size(); + logger.info("After deploy: deployed custom model count: "+newDeployedModelCount); + assertEquals(deployedModelCount+n, newDeployedModelCount); for (int i = 1; i <= n; i++) { assertTrue(isModelDeployed(modelPrefix+i)); } - assertEquals(dictModelCount+n, getModelCount()); + int newDictModelCount = getModelCount(); + logger.info("After deploy: dictionary model count: "+newDictModelCount); + assertEquals(dictModelCount+n, newDictModelCount); undeployModels(n); + + newDeployedModelCount = repoAdminService.getModels().size(); + logger.info("After undeploy: deployed custom model count: "+newDeployedModelCount); + assertEquals(deployedModelCount, newDeployedModelCount); + + newDictModelCount = getModelCount(); + logger.info("After undeploy: dictionary model count: "+newDictModelCount); + assertEquals(dictModelCount, newDictModelCount); } public void testConcurrentDynamicModelDelete() throws Exception { - final int n = 5; + final int n = 2; undeployModels(n); @@ -591,22 +621,30 @@ public class RepoAdminServiceImplTest extends TestCase { AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - if (opType == 1) + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() { - // Deploy model - String model = MODEL_MKR_XML.replace(MKR, i+""); - InputStream modelStream = new ByteArrayInputStream(model.getBytes("UTF-8")); - repoAdminService.deployModel(modelStream, modelPrefix+i); - - logger.info("["+i+"] Deploying - test model: "+modelPrefix+i); - } - else if (opType == 2) - { - // Undeploy model - repoAdminService.undeployModel(modelPrefix+i); - - logger.info("["+i+"] Undeployed - test model: "+modelPrefix+i); - } + public Object execute() throws Throwable + { + if (opType == 1) + { + // Deploy model + String model = MODEL_MKR_XML.replace(MKR, i+""); + InputStream modelStream = new ByteArrayInputStream(model.getBytes("UTF-8")); + repoAdminService.deployModel(modelStream, modelPrefix+i); + + logger.info("["+i+"] Deploying - test model: "+modelPrefix+i); + } + else if (opType == 2) + { + // Undeploy model + repoAdminService.undeployModel(modelPrefix+i); + + logger.info("["+i+"] Undeployed - test model: "+modelPrefix+i); + } + + return null; + } + }); } catch (Throwable t) {