From a576035f0fa6e9875642f7e3bc9713ca15665a01 Mon Sep 17 00:00:00 2001 From: Mark Rogers Date: Wed, 23 Jul 2014 16:02:04 +0000 Subject: [PATCH] Merged HEAD-BUG-FIX (5.0/Cloud) to HEAD (5.0/Cloud) 77150: Merged PLATFORM1 (5.0/Cloud) to HEAD-BUG-FIX (5.0/Cloud) 73977: ACE-1802 "MT / Cloud Restrict namespace URI of dynamic models." ACE-955 "Custom Content Models in Cloud" git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@78008 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/core-services-context.xml | 27 +- config/alfresco/opencmis-context.xml | 6 +- config/alfresco/policy-context.xml | 12 +- pom.xml | 19 + .../opencmis/AlfrescoCmisServiceImpl.java | 29 +- .../repo/admin/RepoAdminServiceImpl.java | 2 +- .../repo/dictionary/DictionaryModelType.java | 413 +---------------- .../DictionaryRepositoryBootstrap.java | 125 +++--- .../DynamicCreateRepositoryLocation.java | 150 +++++++ .../repo/dictionary/ModelValidator.java | 17 + .../repo/dictionary/ModelValidatorImpl.java | 421 ++++++++++++++++++ .../repo/dictionary/RepositoryLocation.java | 7 +- .../alfresco/repo/dictionary/TestModel.java | 21 +- .../repo/version/VersionableAspect.java | 2 +- .../org/alfresco/AllUnitTestsSuite.java | 3 + .../org/alfresco/opencmis/BaseCMISTest.java | 6 +- .../alfresco/opencmis/CMISDictionaryTest.java | 68 +++ .../org/alfresco/opencmis/CMISTest.java | 2 +- .../DictionaryDAOIntegrationTest.java | 191 ++++++++ .../repo/dictionary/DictionaryDAOTest.java | 148 ++++++ .../dictionary/DictionaryLoadDAOTest.java | 147 ++++++ .../dictionary/DictionaryModelTypeTest.java | 7 +- .../dictionary/RepoDictionaryDAOTest.java | 47 +- .../alfresco/repo/jscript/ScriptNodeTest.java | 13 +- .../repo/policy/MTPolicyComponentTest.java | 20 +- .../repo/policy/PolicyComponentTest.java | 20 +- .../search/impl/lucene/ADMLuceneTest.java | 16 +- .../impl/querymodel/impl/db/DBQueryTest.java | 8 +- .../dictionarydaotest_model1.properties | 21 + .../dictionary/dictionarydaotest_model1.xml | 85 ++++ .../dictionarytest_model1.properties | 21 + .../dictionary/dictionarytest_model1.xml | 85 ++++ 32 files changed, 1576 insertions(+), 583 deletions(-) create mode 100644 source/java/org/alfresco/repo/dictionary/DynamicCreateRepositoryLocation.java create mode 100644 source/java/org/alfresco/repo/dictionary/ModelValidator.java create mode 100644 source/java/org/alfresco/repo/dictionary/ModelValidatorImpl.java create mode 100644 source/test-java/org/alfresco/opencmis/CMISDictionaryTest.java create mode 100644 source/test-java/org/alfresco/repo/dictionary/DictionaryDAOIntegrationTest.java create mode 100644 source/test-java/org/alfresco/repo/dictionary/DictionaryDAOTest.java create mode 100644 source/test-java/org/alfresco/repo/dictionary/DictionaryLoadDAOTest.java create mode 100644 source/test-resources/dictionary/dictionarydaotest_model1.properties create mode 100644 source/test-resources/dictionary/dictionarydaotest_model1.xml create mode 100644 source/test-resources/dictionary/dictionarytest_model1.properties create mode 100644 source/test-resources/dictionary/dictionarytest_model1.xml diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml index bf29bfdcf2..adee588308 100644 --- a/config/alfresco/core-services-context.xml +++ b/config/alfresco/core-services-context.xml @@ -713,20 +713,25 @@ - - - - - - - - + + + + + + + + + + + + + ${spaces.store} + ${spaces.archive.store} + + - - - diff --git a/config/alfresco/opencmis-context.xml b/config/alfresco/opencmis-context.xml index 60eacd1421..daa6454308 100644 --- a/config/alfresco/opencmis-context.xml +++ b/config/alfresco/opencmis-context.xml @@ -37,22 +37,24 @@ - + + - + + diff --git a/config/alfresco/policy-context.xml b/config/alfresco/policy-context.xml index 33b5328639..e3dd35c25f 100644 --- a/config/alfresco/policy-context.xml +++ b/config/alfresco/policy-context.xml @@ -62,20 +62,10 @@ - - - - + - - - - ${spaces.store} - ${spaces.archive.store} - - diff --git a/pom.xml b/pom.xml index 904cc51512..57f3def2d7 100644 --- a/pom.xml +++ b/pom.xml @@ -928,6 +928,25 @@ + + + + org.commonjava.maven.plugins + + + directory-maven-plugin + + + [0.1,) + + + highest-basedir + + + + + + diff --git a/source/java/org/alfresco/opencmis/AlfrescoCmisServiceImpl.java b/source/java/org/alfresco/opencmis/AlfrescoCmisServiceImpl.java index 402fad7aa9..7f11484059 100644 --- a/source/java/org/alfresco/opencmis/AlfrescoCmisServiceImpl.java +++ b/source/java/org/alfresco/opencmis/AlfrescoCmisServiceImpl.java @@ -279,16 +279,17 @@ public class AlfrescoCmisServiceImpl extends AbstractCmisService implements Alfr List childrenList; if (typeId == null) { - childrenList = connector.getOpenCMISDictionaryService().getBaseTypes(); + childrenList = connector.getOpenCMISDictionaryService().getBaseTypes(true); } else { - TypeDefinitionWrapper tdw = connector.getOpenCMISDictionaryService().findType(typeId); - if (tdw == null) - { - throw new CmisObjectNotFoundException("Type '" + typeId + "' is unknown!"); - } - childrenList = tdw.getChildren(); + TypeDefinitionWrapper tdw = connector.getOpenCMISDictionaryService().findType(typeId); + if (tdw == null) + { + throw new CmisObjectNotFoundException("Type '" + typeId + "' is unknown!"); + } + childrenList = connector.getOpenCMISDictionaryService().getChildren(typeId); +// childrenList = tdw.getChildren(); } // create result @@ -341,7 +342,7 @@ public class AlfrescoCmisServiceImpl extends AbstractCmisService implements Alfr if (typeId == null) { - for (TypeDefinitionWrapper tdw : connector.getOpenCMISDictionaryService().getBaseTypes()) + for (TypeDefinitionWrapper tdw : connector.getOpenCMISDictionaryService().getBaseTypes(true)) { result.add(getTypesDescendants(d, tdw, includePropertyDefinitions)); } @@ -353,10 +354,10 @@ public class AlfrescoCmisServiceImpl extends AbstractCmisService implements Alfr { throw new CmisObjectNotFoundException("Type '" + typeId + "' is unknown!"); } - - if (tdw.getChildren() != null) + List children = connector.getOpenCMISDictionaryService().getChildren(typeId); + if(children != null) { - for (TypeDefinitionWrapper child : tdw.getChildren()) + for (TypeDefinitionWrapper child : children) { result.add(getTypesDescendants(d, child, includePropertyDefinitions)); } @@ -378,10 +379,12 @@ public class AlfrescoCmisServiceImpl extends AbstractCmisService implements Alfr if (depth != 0) { - if (tdw.getChildren() != null) + String typeId = tdw.getTypeId(); + List children = connector.getOpenCMISDictionaryService().getChildren(typeId); + if (children != null) { result.setChildren(new ArrayList()); - for (TypeDefinitionWrapper tdc : tdw.getChildren()) + for (TypeDefinitionWrapper tdc : children) { result.getChildren().add( getTypesDescendants(depth < 0 ? -1 : depth - 1, tdc, includePropertyDefinitions)); diff --git a/source/java/org/alfresco/repo/admin/RepoAdminServiceImpl.java b/source/java/org/alfresco/repo/admin/RepoAdminServiceImpl.java index 8578fffab0..6dd6b0bfa7 100644 --- a/source/java/org/alfresco/repo/admin/RepoAdminServiceImpl.java +++ b/source/java/org/alfresco/repo/admin/RepoAdminServiceImpl.java @@ -141,7 +141,7 @@ public class RepoAdminServiceImpl implements RepoAdminService List modelsInRepo = new ArrayList(); - Collection models = dictionaryDAO.getModels(); + Collection models = dictionaryDAO.getModels(true); List dictionaryModels = new ArrayList(); for (QName model : models) diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryModelType.java b/source/java/org/alfresco/repo/dictionary/DictionaryModelType.java index 2e45384171..4206e56063 100644 --- a/source/java/org/alfresco/repo/dictionary/DictionaryModelType.java +++ b/source/java/org/alfresco/repo/dictionary/DictionaryModelType.java @@ -21,14 +21,11 @@ package org.alfresco.repo.dictionary; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; -import java.util.Collection; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; -import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.ContentServicePolicies; import org.alfresco.repo.lock.JobLockService; @@ -38,34 +35,17 @@ import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.tenant.Tenant; -import org.alfresco.repo.tenant.TenantAdminService; import org.alfresco.repo.tenant.TenantService; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; -import org.alfresco.repo.transaction.TransactionListenerAdapter; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.repo.transaction.TransactionListenerAdapter; import org.alfresco.repo.version.Version2Model; -import org.alfresco.repo.workflow.BPMEngineRegistry; -import org.alfresco.service.cmr.dictionary.AspectDefinition; -import org.alfresco.service.cmr.dictionary.ClassDefinition; -import org.alfresco.service.cmr.dictionary.ConstraintDefinition; -import org.alfresco.service.cmr.dictionary.DictionaryException; import org.alfresco.service.cmr.dictionary.ModelDefinition; -import org.alfresco.service.cmr.dictionary.NamespaceDefinition; -import org.alfresco.service.cmr.dictionary.PropertyDefinition; -import org.alfresco.service.cmr.dictionary.TypeDefinition; 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.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.workflow.WorkflowDefinition; -import org.alfresco.service.cmr.workflow.WorkflowService; -import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition; -import org.alfresco.service.namespace.NamespaceException; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; @@ -116,30 +96,18 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda /** The policy component */ private PolicyComponent policyComponent; - /** The workflow service */ - private WorkflowService workflowService; - - /** The search service */ - private SearchService searchService; - - /** The namespace service */ - private NamespaceService namespaceService; - /** The tenant service */ private TenantService tenantService; - /** The tenant deployer service */ - private TenantAdminService tenantAdminService; - private TransactionService transactionService; private JobLockService jobLockService; /** Transaction listener */ private DictionaryModelTypeTransactionListener transactionListener; - - private List storeUrls; // stores against which model deletes should be validated - + + private ModelValidator modelValidator; + /** Validation marker */ private boolean doValidation = true; @@ -150,8 +118,13 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda { this.dictionaryDAO = dictionaryDAO; } - - /** + + public void setModelValidator(ModelValidator modelValidator) + { + this.modelValidator = modelValidator; + } + + /** * Set the namespace DOA */ public void setNamespaceDAO(NamespaceDAO namespaceDAO) @@ -182,31 +155,7 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda { this.policyComponent = policyComponent; } - - /** - * Set the workflow service - */ - public void setWorkflowService(WorkflowService workflowService) - { - this.workflowService = workflowService; - } - - /** - * Set the search service - */ - public void setSearchService(SearchService searchService) - { - this.searchService = searchService; - } - - /** - * Set the namespace service - */ - public void setNamespaceService(NamespaceService namespaceService) - { - this.namespaceService = namespaceService; - } - + /** * Set the tenant service */ @@ -214,15 +163,7 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda { this.tenantService = tenantService; } - - /** - * Set the tenant admin service - */ - public void setTenantAdminService(TenantAdminService tenantAdminService) - { - this.tenantAdminService = tenantAdminService; - } - + /** * Set the transaction service */ @@ -235,12 +176,7 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda { this.jobLockService = jobLockService; } - - public void setStoreUrls(List storeUrls) - { - this.storeUrls = storeUrls; - } - + public void setDoValidation(boolean doValidation) { this.doValidation = doValidation; @@ -403,7 +339,7 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda if (modelName != null) { // Validate model delete against usages - content and/or workflows - validateModelDelete(modelName); + modelValidator.validateModelDelete(modelName); Set pendingModelDeletes = (Set)AlfrescoTransactionSupport.getResource(KEY_PENDING_DELETE_MODELS); if (pendingModelDeletes == null) @@ -484,7 +420,7 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda } } } - + /** * Dictionary model type transaction listener class. */ @@ -693,10 +629,11 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda // Validate model against dictionary - could be new, unchanged or updated if (doValidation == true) { - validateModel(modelDefinition.getName(), m2Model, compiledModel); + modelValidator.validateModel(compiledModel); } - + // invalidate - to force lazy re-init + // TODO //dictionaryDAO.destroy(); if (logger.isTraceEnabled()) @@ -711,7 +648,7 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda if (modelName != null) { // Validate model delete against usages - content and/or workflows - validateModelDelete(modelName); + modelValidator.validateModelDelete(modelName); // invalidate - to force lazy re-init //dictionaryDAO.destroy(); @@ -752,314 +689,4 @@ public class DictionaryModelType implements ContentServicePolicies.OnContentUpda } } } - - /** - * validate against repository contents / workflows (e.g. when deleting an existing model) - * - * @param modelName - */ - private void validateModelDelete(final QName modelName) - { - // TODO add model locking during delete (would need to be tenant-aware & cluster-aware) to avoid potential - // for concurrent addition of new content/workflow as model is being deleted - - final Collection namespaceDefs; - final Collection typeDefs; - final Collection aspectDefs; - - try - { - namespaceDefs = dictionaryDAO.getNamespaces(modelName); - typeDefs = dictionaryDAO.getTypes(modelName); - aspectDefs = dictionaryDAO.getAspects(modelName); - } - catch (DictionaryException e) - { - if (logger.isDebugEnabled()) - { - logger.debug("Dictionary model '" + modelName + "' does not exist ... skip delete validation : " + e); - } - return; - } - - // TODO - in case of MT we do not currently allow deletion of an overridden model (with usages) ... but could allow if (re-)inherited model is equivalent to an incremental update only ? - validateModelDelete(namespaceDefs, typeDefs, aspectDefs, false); - - if (tenantService.isEnabled() && tenantService.isTenantUser() == false) - { - // shared model - need to check all tenants (whether enabled or disabled) unless they have overridden - List tenants = tenantAdminService.getAllTenants(); - for (Tenant tenant : tenants) - { - // validate model delete within context of tenant domain - AuthenticationUtil.runAs(new RunAsWork() - { - public Object doWork() - { - if (dictionaryDAO.isModelInherited(modelName)) - { - validateModelDelete(namespaceDefs, typeDefs, aspectDefs, true); - } - return null; - } - }, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenant.getTenantDomain())); - } - } - } - - private void validateModelDelete(Collection namespaceDefs, Collection typeDefs, Collection aspectDefs, boolean sharedModel) - { - String tenantDomain = TenantService.DEFAULT_DOMAIN; - if (sharedModel) - { - tenantDomain = " for tenant [" + tenantService.getCurrentUserDomain() + "]"; - } - - List workflowDefs = workflowService.getDefinitions(); - - if (workflowDefs.size() > 0) - { - if (namespaceDefs.size() > 0) - { - // check workflow namespace usage - for (WorkflowDefinition workflowDef : workflowDefs) - { - String workflowDefName = workflowDef.getName(); - - String workflowNamespaceURI = null; - try - { - workflowNamespaceURI = QName.createQName(BPMEngineRegistry.getLocalId(workflowDefName), namespaceService).getNamespaceURI(); - } - catch (NamespaceException ne) - { - logger.warn("Skipped workflow when validating model delete - unknown namespace: "+ne); - continue; - } - - for (NamespaceDefinition namespaceDef : namespaceDefs) - { - if (workflowNamespaceURI.equals(namespaceDef.getUri())) - { - throw new AlfrescoRuntimeException("Failed to validate model delete" + tenantDomain + " - found workflow process definition " + workflowDefName + " using model namespace '" + namespaceDef.getUri() + "'"); - } - } - } - } - } - - // check for type usages - for (TypeDefinition type : typeDefs) - { - validateClass(tenantDomain, type); - } - - // check for aspect usages - for (AspectDefinition aspect : aspectDefs) - { - validateClass(tenantDomain, aspect); - } - } - - private void validateClass(String tenantDomain, ClassDefinition classDef) - { - QName className = classDef.getName(); - - String classType = "TYPE"; - if (classDef instanceof AspectDefinition) - { - classType = "ASPECT"; - } - - for (String storeUrl : this.storeUrls) - { - StoreRef store = new StoreRef(storeUrl); - - // search for TYPE or ASPECT - TODO - alternative would be to extract QName and search by namespace ... - ResultSet rs = searchService.query(store, SearchService.LANGUAGE_LUCENE, classType+":\""+className+"\""); - try - { - if (rs.length() > 0) - { - throw new AlfrescoRuntimeException("Failed to validate model delete" + tenantDomain + " - found " + rs.length() + " nodes in store " + store + " with " + classType + " '" + className + "'" ); - } - } - finally - { - rs.close(); - } - } - - // check against workflow task usage - for (WorkflowDefinition workflowDef : workflowService.getDefinitions()) - { - for (WorkflowTaskDefinition workflowTaskDef : workflowService.getTaskDefinitions(workflowDef.getId())) - { - TypeDefinition workflowTypeDef = workflowTaskDef.metadata; - if (workflowTypeDef.getName().equals(className)) - { - throw new AlfrescoRuntimeException("Failed to validate model delete" + tenantDomain + " - found task definition in workflow " + workflowDef.getName() + " with " + classType + " '" + className + "'"); - } - } - } - } - - /** - * validate against dictionary - * - * if new model - * then nothing to validate - * - * else if an existing model - * then could be updated (or unchanged) so validate to currently only allow incremental updates - * - addition of new types, aspects (except default aspects), properties, associations - * - no deletion of types, aspects or properties or associations - * - no addition, update or deletion of default/mandatory aspects - * - * @paramn modelName - * @param newOrUpdatedModel - */ - private void validateModel(QName modelName, M2Model model, CompiledModel compiledModel) - { - List modelDiffs = dictionaryDAO.diffModel(model); - - for (M2ModelDiff modelDiff : modelDiffs) - { - if (modelDiff.getDiffType().equals(M2ModelDiff.DIFF_DELETED)) - { - // TODO - check tenants if model is shared / inherited - if (modelDiff.getElementType().equals(M2ModelDiff.TYPE_PROPERTY)) - { - validatePropertyDelete(modelName, modelDiff.getElementName(), false); - - continue; - } - else if (modelDiff.getElementType().equals(M2ModelDiff.TYPE_CONSTRAINT)) - { - validateConstraintDelete(compiledModel, modelDiff.getElementName(), false); - continue; - } - else - { - throw new AlfrescoRuntimeException("Failed to validate model update - found deleted " + modelDiff.getElementType() + " '" + modelDiff.getElementName() + "'"); - } - } - - if (modelDiff.getDiffType().equals(M2ModelDiff.DIFF_UPDATED)) - { - throw new AlfrescoRuntimeException("Failed to validate model update - found non-incrementally updated " + modelDiff.getElementType() + " '" + modelDiff.getElementName() + "'"); - } - } - - // TODO validate that any deleted constraints are not being referenced - else currently will become anon - or push down into model compilation (check backwards compatibility ...) - } - - private void validatePropertyDelete(QName modelName, QName propertyName, boolean sharedModel) - { - String tenantDomain = TenantService.DEFAULT_DOMAIN; - if (sharedModel) - { - tenantDomain = " for tenant [" + tenantService.getCurrentUserDomain() + "]"; - } - - boolean found = false; - - // check for property usages - for (PropertyDefinition prop : dictionaryDAO.getProperties(modelName, null)) - { - // TODO ... match property - if (prop.getName().equals(propertyName)) - { - // found - found = true; - validateIndexedProperty(tenantDomain, prop); - break; - } - } - - if (! found) - { - throw new AlfrescoRuntimeException("Failed to validate property delete" + tenantDomain + " - property definition '" + propertyName + "' not defined in model '" + modelName + "'"); - } - } - - private void validateIndexedProperty(String tenantDomain, PropertyDefinition propDef) - { - QName propName = propDef.getName(); - - if (! propDef.isIndexed()) - { - // TODO ... implement DB-level referential integrity - throw new AlfrescoRuntimeException("Failed to validate property delete" + tenantDomain + " - cannot delete unindexed property definition '" + propName); - } - - for (String storeUrl : this.storeUrls) - { - StoreRef store = new StoreRef(storeUrl); - - // search for indexed PROPERTY - String escapePropName = propName.toPrefixString().replace(":", "\\:"); - ResultSet rs = searchService.query(store, SearchService.LANGUAGE_LUCENE, "@"+escapePropName+":*"); - try - { - if (rs.length() > 0) - { - throw new AlfrescoRuntimeException("Failed to validate property delete" + tenantDomain + " - found " + rs.length() + " nodes in store " + store + " with PROPERTY '" + propName + "'" ); - } - } - finally - { - rs.close(); - } - } - } - - // validate delete of a referencable constraint def - private void validateConstraintDelete(CompiledModel compiledModel, QName constraintName, boolean sharedModel) - { - String tenantDomain = TenantService.DEFAULT_DOMAIN; - if (sharedModel) - { - tenantDomain = " for tenant [" + tenantService.getCurrentUserDomain() + "]"; - } - - Set referencedBy = new HashSet(0); - - // check for references to constraint definition - // note: could be anon prop constraint (if no referenceable constraint) - Collection allModels = dictionaryDAO.getModels(); - for (QName model : allModels) - { - Collection propDefs = null; - if (compiledModel.getModelDefinition().getName().equals(model)) - { - // TODO deal with multiple pending model updates - propDefs = compiledModel.getProperties(); - } - else - { - propDefs = dictionaryDAO.getProperties(model); - } - - for (PropertyDefinition propDef : propDefs) - { - for (ConstraintDefinition conDef : propDef.getConstraints()) - { - if (constraintName.equals(conDef.getRef())) - { - referencedBy.add(conDef.getName()); - } - } - } - } - - if (referencedBy.size() == 1) - { - throw new AlfrescoRuntimeException("Failed to validate constraint delete" + tenantDomain + " - constraint definition '" + constraintName + "' is being referenced by '" + referencedBy.toArray()[0] + "' property constraint"); - } - else if (referencedBy.size() > 1) - { - throw new AlfrescoRuntimeException("Failed to validate constraint delete" + tenantDomain + " - constraint definition '" + constraintName + "' is being referenced by " + referencedBy.size() + " property constraints"); - } - } } diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryRepositoryBootstrap.java b/source/java/org/alfresco/repo/dictionary/DictionaryRepositoryBootstrap.java index a53996fdd2..9369d28b82 100644 --- a/source/java/org/alfresco/repo/dictionary/DictionaryRepositoryBootstrap.java +++ b/source/java/org/alfresco/repo/dictionary/DictionaryRepositoryBootstrap.java @@ -64,9 +64,10 @@ import org.alfresco.repo.dictionary.DynamicModelPolicies.OnLoadDynamicModel; /** * Bootstrap the dictionary from specified locations within the repository * - * @author Roy Wetherall, JanV + * @author Roy Wetherall, JanV, sglover */ -public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean implements TenantDeployer, DictionaryListener, MessageDeployer +public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean +implements TenantDeployer, DictionaryListener, /*TenantDictionaryListener, */MessageDeployer { // Logging support private static Log logger = LogFactory.getLog(DictionaryRepositoryBootstrap.class); @@ -131,7 +132,17 @@ public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean impleme { this.nodeService = nodeService; } - + + public PolicyComponent getPolicyComponent() + { + return policyComponent; + } + + public void setPolicyComponent(PolicyComponent policyComponent) + { + this.policyComponent = policyComponent; + } + /** * Set the tenant admin service * @@ -231,29 +242,7 @@ public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean impleme { // NOOP - will be destroyed directly via DictionaryComponent } - - /** - * Initialise the dictionary, ensuring that a transaction is available - */ - @Override - public void onDictionaryInit() - { - if(onLoadDynamicModelDelegate == null) - { - onLoadDynamicModelDelegate = policyComponent.registerClassPolicy(DynamicModelPolicies.OnLoadDynamicModel.class); - } - RetryingTransactionCallback initCallback = new RetryingTransactionCallback() - { - @Override - public Void execute() throws Throwable - { - onDictionaryInitInTxn(); - return null; - } - }; - transactionService.getRetryingTransactionHelper().doInTransaction(initCallback, true, false); - } - + /** * Perform the actual repository access, checking for the existence of a valid transaction */ @@ -272,7 +261,7 @@ public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean impleme logger.trace("onDictionaryInit: ["+Thread.currentThread()+"]"+(tenantDomain.equals(TenantService.DEFAULT_DOMAIN) ? "" : " (Tenant: "+tenantDomain+")")); } - Collection modelsBefore = dictionaryDAO.getModels(); // note: re-entrant + Collection modelsBefore = dictionaryDAO.getModels(true); // note: re-entrant int modelsBeforeCnt = (modelsBefore != null ? modelsBefore.size() : 0); List loadedModels = new ArrayList(); @@ -312,7 +301,8 @@ public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean impleme try { // Ignore if the node is a working copy or archived, or if its inactive - if (! (nodeService.hasAspect(dictionaryModel, ContentModel.ASPECT_WORKING_COPY) || nodeService.hasAspect(dictionaryModel, ContentModel.ASPECT_ARCHIVED))) + if (! (nodeService.hasAspect(dictionaryModel, ContentModel.ASPECT_WORKING_COPY) || + nodeService.hasAspect(dictionaryModel, ContentModel.ASPECT_ARCHIVED))) { Boolean isActive = (Boolean)nodeService.getProperty(dictionaryModel, ContentModel.PROP_MODEL_ACTIVE); @@ -363,7 +353,7 @@ public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean impleme } } - Collection modelsAfter = dictionaryDAO.getModels(); + Collection modelsAfter = dictionaryDAO.getModels(true); int modelsAfterCnt = (modelsAfter != null ? modelsAfter.size() : 0); if (logger.isDebugEnabled()) @@ -383,23 +373,7 @@ public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean impleme DynamicModelPolicies.OnLoadDynamicModel policy = onLoadDynamicModelDelegate.get(ContentModel.TYPE_CONTENT); policy.onLoadDynamicModel(entry.model, entry.nodeRef); } - - /* - * (non-Javadoc) - * @see org.alfresco.repo.dictionary.DictionaryListener#afterInit() - */ - public void afterDictionaryInit() - { - } - - /* - * (non-Javadoc) - * @see org.alfresco.repo.dictionary.DictionaryListener#onDictionaryDestroy() - */ - public void afterDictionaryDestroy() - { - } - + public void initMessages() { if (this.repositoryMessagesLocations != null) @@ -496,14 +470,20 @@ public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean impleme return modelRefs; } - - protected List getNodes(StoreRef storeRef, RepositoryLocation repositoryLocation, QName nodeType) + + protected List getNodes(StoreRef storeRef, RepositoryLocation repositoryLocation, QName nodeType) { List nodeRefs = new ArrayList(); - + NodeRef rootNodeRef = nodeService.getRootNode(storeRef); + + if(repositoryLocation instanceof DynamicCreateRepositoryLocation) + { + ((DynamicCreateRepositoryLocation)repositoryLocation).checkAndCreate(rootNodeRef); + } + String[] pathElements = repositoryLocation.getPathElements(); - + NodeRef folderNodeRef = rootNodeRef; if (pathElements.length > 0) { @@ -575,10 +555,12 @@ public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean impleme { if (logger.isDebugEnabled()) { - logger.debug("Loading model: " + modelName + " (from ["+ modelLocation.getStoreRef() + "]"+ modelLocation.getPath() + ")"); + logger.debug("Loading model: " + modelName + + " (from ["+ modelLocation.getStoreRef() + "]"+ modelLocation.getPath() + ")"); } - + dictionaryDAO.putModel(model); + loadedModels.add(modelName); } catch (AlfrescoRuntimeException e) @@ -666,8 +648,8 @@ public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean impleme dictionaryDAO.destroy(); // register with Dictionary Service to allow (re-)init - dictionaryDAO.register(this); - + dictionaryDAO.registerListener(this); + // register with Message Service to allow (re-)init messageService.register(this); @@ -742,13 +724,36 @@ public class DictionaryRepositoryBootstrap extends AbstractLifecycleBean impleme } return parentNodeRef; } - - - public PolicyComponent getPolicyComponent() { - return policyComponent; + + /** + * Initialise the dictionary, ensuring that a transaction is available + */ + @Override + public void onDictionaryInit() + { + if(onLoadDynamicModelDelegate == null) + { + onLoadDynamicModelDelegate = policyComponent.registerClassPolicy(DynamicModelPolicies.OnLoadDynamicModel.class); + } + RetryingTransactionCallback initCallback = new RetryingTransactionCallback() + { + @Override + public Void execute() throws Throwable + { + onDictionaryInitInTxn(); + return null; + } + }; + transactionService.getRetryingTransactionHelper().doInTransaction(initCallback, true, false); + } + + @Override + public void afterDictionaryDestroy() + { } - public void setPolicyComponent(PolicyComponent policyComponent) { - this.policyComponent = policyComponent; + @Override + public void afterDictionaryInit() + { } } diff --git a/source/java/org/alfresco/repo/dictionary/DynamicCreateRepositoryLocation.java b/source/java/org/alfresco/repo/dictionary/DynamicCreateRepositoryLocation.java new file mode 100644 index 0000000000..c66ec11812 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/DynamicCreateRepositoryLocation.java @@ -0,0 +1,150 @@ +package org.alfresco.repo.dictionary; + +import java.io.File; +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +import org.alfresco.repo.importer.ACPImportPackageHandler; +import org.alfresco.repo.importer.ImporterBootstrap; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.view.ImportPackageHandler; +import org.alfresco.service.cmr.view.ImporterBinding; +import org.alfresco.service.cmr.view.ImporterContentCache; +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.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * + * @author sglover + * + */ +public class DynamicCreateRepositoryLocation extends RepositoryLocation +{ + private static final Log logger = LogFactory.getLog(DynamicCreateRepositoryLocation.class); + + private ImporterService importerService; + private String contentViewLocation; + private ResourceBundle bundle; + private NamespaceService namespaceService; + private SearchService searchService; + + public void setSearchService(SearchService searchService) + { + this.searchService = searchService; + } + + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + public void setContentViewLocation(String contentViewLocation) + { + this.contentViewLocation = contentViewLocation; + } + + public void setImporterService(ImporterService importerService) + { + this.importerService = importerService; + } + + public void setBundleName(String bundleName) + { + Locale bindingLocale = I18NUtil.getLocale(); + this.bundle = ResourceBundle.getBundle(bundleName, bindingLocale); + } + + public void checkAndCreate(NodeRef rootNodeRef) + { +// try +// { +// String[] pathElements = getPathElements(); + List nodes = searchService.selectNodes(rootNodeRef, getPath(), null, namespaceService, false); + if(nodes.size() == 0) + { + logger.info("Repository location " + getPath() + " does not exist for tenant " + + TenantUtil.getCurrentDomain() + ", creating"); + create(); + } + +// fileFolderService.resolveNamePath(rootNodeRef, Arrays.asList(pathElements)); +// } +// catch(FileNotFoundException e) +// { +// logger.info("Repository location " + getPath() + " does not exist for tenant " +// + TenantUtil.getCurrentDomain() + ", creating"); +// create(); +// } + } + + protected String getParentPath() + { + String parentPath = null; + + String path = getPath(); + int idx = path.lastIndexOf("/"); + if(idx != -1) + { + parentPath = path.substring(0, idx); + } + else + { + parentPath = "/"; + } + + return parentPath; + } + + protected void create() + { + final File viewFile = ImporterBootstrap.getFile(contentViewLocation); + ImportPackageHandler acpHandler = new ACPImportPackageHandler(viewFile, null); + Location location = new Location(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); + location.setPath(getParentPath()); + + final ImporterBinding binding = new ImporterBinding() + { + @Override + public String getValue(String key) + { + return bundle.getString(key); + } + + @Override + public UUID_BINDING getUUIDBinding() + { + return UUID_BINDING.CREATE_NEW; + } + + @Override + public QName[] getExcludedClasses() + { + return null; + } + + @Override + public boolean allowReferenceWithinTransaction() + { + return false; + } + + @Override + public ImporterContentCache getImportConentCache() + { + return null; + } + }; + + importerService.importView(acpHandler, location, binding, (ImporterProgress) null); + } +} diff --git a/source/java/org/alfresco/repo/dictionary/ModelValidator.java b/source/java/org/alfresco/repo/dictionary/ModelValidator.java new file mode 100644 index 0000000000..102956983e --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/ModelValidator.java @@ -0,0 +1,17 @@ +package org.alfresco.repo.dictionary; + +import java.util.List; + +import org.alfresco.service.namespace.QName; + +/** + * + * @author sglover + * + */ +public interface ModelValidator +{ + void setStoreUrls(List storeUrls); + void validateModel(CompiledModel compiledModel); + void validateModelDelete(final QName modelName); +} diff --git a/source/java/org/alfresco/repo/dictionary/ModelValidatorImpl.java b/source/java/org/alfresco/repo/dictionary/ModelValidatorImpl.java new file mode 100644 index 0000000000..b0da75673c --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/ModelValidatorImpl.java @@ -0,0 +1,421 @@ +package org.alfresco.repo.dictionary; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.tenant.Tenant; +import org.alfresco.repo.tenant.TenantAdminService; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.workflow.BPMEngineRegistry; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.NamespaceDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +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.workflow.WorkflowDefinition; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition; +import org.alfresco.service.namespace.NamespaceException; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author sglover + * + */ +public class ModelValidatorImpl implements ModelValidator +{ + private static final Log logger = LogFactory.getLog(ModelValidatorImpl.class); + + private DictionaryDAO dictionaryDAO; + private NamespaceService namespaceService; + private WorkflowService workflowService; + private TenantService tenantService; + private TenantAdminService tenantAdminService; + private SearchService searchService; + + private List storeUrls; // stores against which model deletes should be validated + + public void setStoreUrls(List storeUrls) + { + this.storeUrls = storeUrls; + } + + public void setDictionaryDAO(DictionaryDAO dictionaryDAO) + { + this.dictionaryDAO = dictionaryDAO; + } + + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + public void setWorkflowService(WorkflowService workflowService) + { + this.workflowService = workflowService; + } + + public void setTenantService(TenantService tenantService) + { + this.tenantService = tenantService; + } + + public void setTenantAdminService(TenantAdminService tenantAdminService) + { + this.tenantAdminService = tenantAdminService; + } + + public void setSearchService(SearchService searchService) + { + this.searchService = searchService; + } + + private void checkCustomModelNamespace(M2Model model, String tenantDomain) + { + if(tenantDomain != null && !tenantDomain.equals("")) + { + // check only for "real" tenants + for(M2Namespace namespace : model.getNamespaces()) + { + String namespaceURI = namespace.getUri(); + if(namespaceURI.indexOf(tenantDomain) == -1) + { + throw new DictionaryException("Namespace " + namespaceURI + " does not contain the tenant " + tenantDomain); + } + } + } + } + + /** + * validate against repository contents / workflows (e.g. when deleting an existing model) + * + * @param modelName + */ + public void validateModelDelete(final QName modelName) + { + // TODO add model locking during delete (would need to be tenant-aware & cluster-aware) to avoid potential + // for concurrent addition of new content/workflow as model is being deleted + + final Collection namespaceDefs; + final Collection typeDefs; + final Collection aspectDefs; + + try + { + namespaceDefs = dictionaryDAO.getNamespaces(modelName); + typeDefs = dictionaryDAO.getTypes(modelName); + aspectDefs = dictionaryDAO.getAspects(modelName); + } + catch (DictionaryException e) + { + if (logger.isDebugEnabled()) + { + logger.debug("Dictionary model '" + modelName + "' does not exist ... skip delete validation : " + e); + } + return; + } + + // TODO - in case of MT we do not currently allow deletion of an overridden model (with usages) ... but could allow if (re-)inherited model is equivalent to an incremental update only ? + validateModelDelete(namespaceDefs, typeDefs, aspectDefs, false); + + if (tenantService.isEnabled() && tenantService.isTenantUser() == false) + { + // shared model - need to check all tenants (whether enabled or disabled) unless they have overridden + List tenants = tenantAdminService.getAllTenants(); + for (Tenant tenant : tenants) + { + // validate model delete within context of tenant domain + AuthenticationUtil.runAs(new RunAsWork() + { + public Object doWork() + { + if (dictionaryDAO.isModelInherited(modelName)) + { + validateModelDelete(namespaceDefs, typeDefs, aspectDefs, true); + } + return null; + } + }, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenant.getTenantDomain())); + } + } + } + + private void validateModelDelete(Collection namespaceDefs, Collection typeDefs, Collection aspectDefs, boolean sharedModel) + { + String tenantDomain = TenantService.DEFAULT_DOMAIN; + if (sharedModel) + { + tenantDomain = " for tenant [" + tenantService.getCurrentUserDomain() + "]"; + } + + List workflowDefs = workflowService.getDefinitions(); + + if (workflowDefs.size() > 0) + { + if (namespaceDefs.size() > 0) + { + // check workflow namespace usage + for (WorkflowDefinition workflowDef : workflowDefs) + { + String workflowDefName = workflowDef.getName(); + + String workflowNamespaceURI = null; + try + { + workflowNamespaceURI = QName.createQName(BPMEngineRegistry.getLocalId(workflowDefName), namespaceService).getNamespaceURI(); + } + catch (NamespaceException ne) + { + logger.warn("Skipped workflow when validating model delete - unknown namespace: "+ne); + continue; + } + + for (NamespaceDefinition namespaceDef : namespaceDefs) + { + if (workflowNamespaceURI.equals(namespaceDef.getUri())) + { + throw new AlfrescoRuntimeException("Failed to validate model delete" + tenantDomain + " - found workflow process definition " + workflowDefName + " using model namespace '" + namespaceDef.getUri() + "'"); + } + } + } + } + } + + // check for type usages + for (TypeDefinition type : typeDefs) + { + validateClass(tenantDomain, type); + } + + // check for aspect usages + for (AspectDefinition aspect : aspectDefs) + { + validateClass(tenantDomain, aspect); + } + } + + private void validateClass(String tenantDomain, ClassDefinition classDef) + { + QName className = classDef.getName(); + + String classType = "TYPE"; + if (classDef instanceof AspectDefinition) + { + classType = "ASPECT"; + } + + for (String storeUrl : this.storeUrls) + { + StoreRef store = new StoreRef(storeUrl); + + // search for TYPE or ASPECT - TODO - alternative would be to extract QName and search by namespace ... + ResultSet rs = searchService.query(store, SearchService.LANGUAGE_LUCENE, classType+":\""+className+"\""); + try + { + if (rs.length() > 0) + { + throw new AlfrescoRuntimeException("Failed to validate model delete" + tenantDomain + " - found " + rs.length() + " nodes in store " + store + " with " + classType + " '" + className + "'" ); + } + } + finally + { + rs.close(); + } + } + + // check against workflow task usage + for (WorkflowDefinition workflowDef : workflowService.getDefinitions()) + { + for (WorkflowTaskDefinition workflowTaskDef : workflowService.getTaskDefinitions(workflowDef.getId())) + { + TypeDefinition workflowTypeDef = workflowTaskDef.metadata; + if (workflowTypeDef.getName().equals(className)) + { + throw new AlfrescoRuntimeException("Failed to validate model delete" + tenantDomain + " - found task definition in workflow " + workflowDef.getName() + " with " + classType + " '" + className + "'"); + } + } + } + } + + /** + * validate against dictionary + * + * if new model + * then nothing to validate + * + * else if an existing model + * then could be updated (or unchanged) so validate to currently only allow incremental updates + * - addition of new types, aspects (except default aspects), properties, associations + * - no deletion of types, aspects or properties or associations + * - no addition, update or deletion of default/mandatory aspects + * + * @paramn modelName + * @param newOrUpdatedModel + */ + @Override + public void validateModel(CompiledModel compiledModel) + { + ModelDefinition modelDef = compiledModel.getModelDefinition(); + QName modelName = modelDef.getName(); + M2Model model = compiledModel.getM2Model(); + + checkCustomModelNamespace(model, TenantUtil.getCurrentDomain()); + + List modelDiffs = dictionaryDAO.diffModel(model); + + for (M2ModelDiff modelDiff : modelDiffs) + { + if (modelDiff.getDiffType().equals(M2ModelDiff.DIFF_DELETED)) + { + // TODO - check tenants if model is shared / inherited + if (modelDiff.getElementType().equals(M2ModelDiff.TYPE_PROPERTY)) + { + validatePropertyDelete(modelName, modelDiff.getElementName(), false); + + continue; + } + else if (modelDiff.getElementType().equals(M2ModelDiff.TYPE_CONSTRAINT)) + { + validateConstraintDelete(compiledModel, modelDiff.getElementName(), false); + continue; + } + else + { + throw new AlfrescoRuntimeException("Failed to validate model update - found deleted " + modelDiff.getElementType() + " '" + modelDiff.getElementName() + "'"); + } + } + + if (modelDiff.getDiffType().equals(M2ModelDiff.DIFF_UPDATED)) + { + throw new AlfrescoRuntimeException("Failed to validate model update - found non-incrementally updated " + modelDiff.getElementType() + " '" + modelDiff.getElementName() + "'"); + } + } + + // TODO validate that any deleted constraints are not being referenced - else currently will become anon - or push down into model compilation (check backwards compatibility ...) + } + + private void validatePropertyDelete(QName modelName, QName propertyName, boolean sharedModel) + { + String tenantDomain = TenantService.DEFAULT_DOMAIN; + if (sharedModel) + { + tenantDomain = " for tenant [" + tenantService.getCurrentUserDomain() + "]"; + } + + boolean found = false; + + // check for property usages + for (PropertyDefinition prop : dictionaryDAO.getProperties(modelName, null)) + { + // TODO ... match property + if (prop.getName().equals(propertyName)) + { + // found + found = true; + validateIndexedProperty(tenantDomain, prop); + break; + } + } + + if (! found) + { + throw new AlfrescoRuntimeException("Failed to validate property delete" + tenantDomain + " - property definition '" + propertyName + "' not defined in model '" + modelName + "'"); + } + } + + private void validateIndexedProperty(String tenantDomain, PropertyDefinition propDef) + { + QName propName = propDef.getName(); + + if (! propDef.isIndexed()) + { + // TODO ... implement DB-level referential integrity + throw new AlfrescoRuntimeException("Failed to validate property delete" + tenantDomain + " - cannot delete unindexed property definition '" + propName); + } + + for (String storeUrl : this.storeUrls) + { + StoreRef store = new StoreRef(storeUrl); + + // search for indexed PROPERTY + String escapePropName = propName.toPrefixString().replace(":", "\\:"); + ResultSet rs = searchService.query(store, SearchService.LANGUAGE_LUCENE, "@"+escapePropName+":*"); + try + { + if (rs.length() > 0) + { + throw new AlfrescoRuntimeException("Failed to validate property delete" + tenantDomain + " - found " + rs.length() + " nodes in store " + store + " with PROPERTY '" + propName + "'" ); + } + } + finally + { + rs.close(); + } + } + } + + // validate delete of a referencable constraint def + private void validateConstraintDelete(CompiledModel compiledModel, QName constraintName, boolean sharedModel) + { + String tenantDomain = TenantService.DEFAULT_DOMAIN; + if (sharedModel) + { + tenantDomain = " for tenant [" + tenantService.getCurrentUserDomain() + "]"; + } + + Set referencedBy = new HashSet(0); + + // check for references to constraint definition + // note: could be anon prop constraint (if no referenceable constraint) + Collection allModels = dictionaryDAO.getModels(true); + for (QName model : allModels) + { + Collection propDefs = null; + if (compiledModel.getModelDefinition().getName().equals(model)) + { + // TODO deal with multiple pending model updates + propDefs = compiledModel.getProperties(); + } + else + { + propDefs = dictionaryDAO.getProperties(model); + } + + for (PropertyDefinition propDef : propDefs) + { + for (ConstraintDefinition conDef : propDef.getConstraints()) + { + if (constraintName.equals(conDef.getRef())) + { + referencedBy.add(conDef.getName()); + } + } + } + } + + if (referencedBy.size() == 1) + { + throw new AlfrescoRuntimeException("Failed to validate constraint delete" + tenantDomain + " - constraint definition '" + constraintName + "' is being referenced by '" + referencedBy.toArray()[0] + "' property constraint"); + } + else if (referencedBy.size() > 1) + { + throw new AlfrescoRuntimeException("Failed to validate constraint delete" + tenantDomain + " - constraint definition '" + constraintName + "' is being referenced by " + referencedBy.size() + " property constraints"); + } + } +} diff --git a/source/java/org/alfresco/repo/dictionary/RepositoryLocation.java b/source/java/org/alfresco/repo/dictionary/RepositoryLocation.java index 4af4621b15..4f88e03c49 100644 --- a/source/java/org/alfresco/repo/dictionary/RepositoryLocation.java +++ b/source/java/org/alfresco/repo/dictionary/RepositoryLocation.java @@ -39,11 +39,10 @@ public class RepositoryLocation /** Search Language */ private String queryLanguage = "xpath"; // default - + public static final String LANGUAGE_PATH = "path"; // lookup directly using node (prefix qname) path public static final String LANGUAGE_CLASSPATH = "classpath"; - - + /** */ public RepositoryLocation() @@ -66,7 +65,7 @@ public class RepositoryLocation setQueryLanguage(queryLanguage); } - /** + /** * Set the store protocol * * @param storeProtocol the store protocol diff --git a/source/java/org/alfresco/repo/dictionary/TestModel.java b/source/java/org/alfresco/repo/dictionary/TestModel.java index f8c7211dc5..ca77fa77ad 100644 --- a/source/java/org/alfresco/repo/dictionary/TestModel.java +++ b/source/java/org/alfresco/repo/dictionary/TestModel.java @@ -23,8 +23,6 @@ import java.util.List; import org.alfresco.repo.cache.DefaultSimpleCache; import org.alfresco.repo.cache.SimpleCache; -import org.alfresco.repo.dictionary.DictionaryDAOImpl.DictionaryRegistry; -import org.alfresco.repo.dictionary.NamespaceDAOImpl.NamespaceRegistry; import org.alfresco.repo.tenant.SingleTServiceImpl; import org.alfresco.repo.tenant.TenantService; @@ -81,12 +79,11 @@ public class TestModel // construct dictionary dao TenantService tenantService = new SingleTServiceImpl(); - NamespaceDAOImpl namespaceDAO = new NamespaceDAOImpl(); - namespaceDAO.setTenantService(tenantService); +// NamespaceDAOImpl namespaceDAO = new NamespaceDAOImpl(); +// namespaceDAO.setTenantService(tenantService); +// initNamespaceCaches(namespaceDAO); - initNamespaceCaches(namespaceDAO); - - DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(namespaceDAO); + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); dictionaryDAO.setTenantService(tenantService); initDictionaryCaches(dictionaryDAO); @@ -122,9 +119,9 @@ public class TestModel dictionaryDAO.setDictionaryRegistryCache(dictionaryCache); } - private static void initNamespaceCaches(NamespaceDAOImpl namespaceDAO) - { - SimpleCache namespaceCache = new DefaultSimpleCache(); - namespaceDAO.setNamespaceRegistryCache(namespaceCache); - } +// private static void initNamespaceCaches(NamespaceDAOImpl namespaceDAO) +// { +// SimpleCache namespaceCache = new DefaultSimpleCache(); +// namespaceDAO.setNamespaceRegistryCache(namespaceCache); +// } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/version/VersionableAspect.java b/source/java/org/alfresco/repo/version/VersionableAspect.java index 230d69e156..d6fa5d7150 100644 --- a/source/java/org/alfresco/repo/version/VersionableAspect.java +++ b/source/java/org/alfresco/repo/version/VersionableAspect.java @@ -255,7 +255,7 @@ public class VersionableAspect implements ContentServicePolicies.OnContentUpdate ContentModel.ASPECT_VERSIONABLE, new JavaBehaviour(this, "getCopyCallback")); - this.dictionaryDAO.register(this); + this.dictionaryDAO.registerListener(this); } /** diff --git a/source/test-java/org/alfresco/AllUnitTestsSuite.java b/source/test-java/org/alfresco/AllUnitTestsSuite.java index 9107d60b2f..7a3d8842a9 100644 --- a/source/test-java/org/alfresco/AllUnitTestsSuite.java +++ b/source/test-java/org/alfresco/AllUnitTestsSuite.java @@ -24,6 +24,9 @@ public class AllUnitTestsSuite extends TestSuite static void unitTests(TestSuite suite) { suite.addTest(new JUnit4TestAdapter(org.alfresco.opencmis.AlfrescoCmisExceptionInterceptorTest.class)); + suite.addTest(new JUnit4TestAdapter(org.alfresco.opencmis.CMISDictionaryTest.class)); + suite.addTest(new JUnit4TestAdapter(org.alfresco.opencmis.CMISTest.class)); + suite.addTestSuite(org.alfresco.cmis.PropertyFilterTest.class); suite.addTestSuite(org.alfresco.encryption.EncryptorTest.class); suite.addTestSuite(org.alfresco.encryption.KeyStoreKeyProviderTest.class); suite.addTest(new JUnit4TestAdapter(org.alfresco.filesys.config.ServerConfigurationBeanTest.class)); diff --git a/source/test-java/org/alfresco/opencmis/BaseCMISTest.java b/source/test-java/org/alfresco/opencmis/BaseCMISTest.java index 6fefe90c14..818e62f1af 100644 --- a/source/test-java/org/alfresco/opencmis/BaseCMISTest.java +++ b/source/test-java/org/alfresco/opencmis/BaseCMISTest.java @@ -29,7 +29,7 @@ import org.alfresco.opencmis.dictionary.CMISDictionaryService; import org.alfresco.opencmis.mapping.CMISMapping; import org.alfresco.opencmis.search.CMISQueryService; import org.alfresco.repo.dictionary.DictionaryDAO; -import org.alfresco.repo.dictionary.NamespaceDAOImpl; +import org.alfresco.repo.dictionary.NamespaceDAO; import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer; import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.security.authentication.AuthenticationUtil; @@ -105,7 +105,7 @@ public abstract class BaseCMISTest extends TestCase protected DictionaryDAO dictionaryDAO; - protected NamespaceDAOImpl namespaceDao; + protected NamespaceDAO namespaceDao; protected VersionService versionService; @@ -145,7 +145,7 @@ public abstract class BaseCMISTest extends TestCase permissionModelDao = (ModelDAO) ctx.getBean("permissionsModelDAO"); dictionaryDAO = (DictionaryDAO) ctx.getBean("dictionaryDAO"); - namespaceDao = (NamespaceDAOImpl) ctx.getBean("namespaceDAO"); + namespaceDao = (NamespaceDAO) ctx.getBean("namespaceDAO"); luceneFTS = (FullTextSearchIndexer)ctx.getBean("LuceneFullTextSearchIndexer"); testTX = transactionService.getUserTransaction(); diff --git a/source/test-java/org/alfresco/opencmis/CMISDictionaryTest.java b/source/test-java/org/alfresco/opencmis/CMISDictionaryTest.java new file mode 100644 index 0000000000..71a6efc99e --- /dev/null +++ b/source/test-java/org/alfresco/opencmis/CMISDictionaryTest.java @@ -0,0 +1,68 @@ +package org.alfresco.opencmis; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.alfresco.opencmis.dictionary.CMISDictionaryService; +import org.alfresco.opencmis.dictionary.TypeDefinitionWrapper; +import org.alfresco.repo.dictionary.DictionaryDAO; +import org.alfresco.repo.dictionary.M2Model; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations={"classpath:alfresco/application-context.xml"}) +public class CMISDictionaryTest +{ + private DictionaryDAO dictionaryDAO; + private CMISDictionaryService cmisDictionaryService; + + @Autowired + private ApplicationContext applicationContext; + + @Before + public void before() + { + this.dictionaryDAO = (DictionaryDAO)applicationContext.getBean("dictionaryDAO"); + this.cmisDictionaryService = (CMISDictionaryService)applicationContext.getBean("OpenCMISDictionaryService1.1"); + } + + @Test + public void test1() + { + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + M2Model customModel = M2Model.createModel( + Thread.currentThread().getContextClassLoader(). + getResourceAsStream("dictionary/dictionarydaotest_model1.xml")); + dictionaryDAO.putModel(customModel); + assertNotNull(cmisDictionaryService.findType("P:cm:dublincore")); + TypeDefinitionWrapper td = cmisDictionaryService.findType("D:daotest1:type1"); + assertNotNull(td); + return null; + } + }, "user1", "tenant1"); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + assertNotNull(cmisDictionaryService.findType("P:cm:dublincore")); + TypeDefinitionWrapper td = cmisDictionaryService.findType("D:daotest1:type1"); + assertNull(td); + return null; + } + }, "user2", "tenant2"); + } +} diff --git a/source/test-java/org/alfresco/opencmis/CMISTest.java b/source/test-java/org/alfresco/opencmis/CMISTest.java index 9e636bf8f7..6a748dedd2 100644 --- a/source/test-java/org/alfresco/opencmis/CMISTest.java +++ b/source/test-java/org/alfresco/opencmis/CMISTest.java @@ -201,7 +201,7 @@ public class CMISTest } } - private static class SimpleCallContext implements CallContext + public static class SimpleCallContext implements CallContext { private final Map contextMap = new HashMap(); private CmisVersion cmisVersion; diff --git a/source/test-java/org/alfresco/repo/dictionary/DictionaryDAOIntegrationTest.java b/source/test-java/org/alfresco/repo/dictionary/DictionaryDAOIntegrationTest.java new file mode 100644 index 0000000000..dd35bff86f --- /dev/null +++ b/source/test-java/org/alfresco/repo/dictionary/DictionaryDAOIntegrationTest.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2005-2011 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.dictionary; + +import static org.junit.Assert.assertNotNull; + +import java.io.ByteArrayOutputStream; +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.opencmis.AlfrescoCmisServiceFactory; +import org.alfresco.opencmis.CMISTest.SimpleCallContext; +import org.alfresco.opencmis.dictionary.CMISDictionaryService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.model.FileNotFoundException; +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.security.MutableAuthenticationService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.PropertyMap; +import org.apache.chemistry.opencmis.commons.enums.CmisVersion; +import org.apache.chemistry.opencmis.commons.server.CallContext; +import org.apache.chemistry.opencmis.commons.server.CmisService; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * + * @author sglover + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations={"classpath:alfresco/application-context.xml"}) +public class DictionaryDAOIntegrationTest +{ + public static final String TEST_RESOURCE_MESSAGES = "alfresco/messages/dictionary-messages"; + + @Autowired + private DictionaryService service; + + @Autowired + private DictionaryDAOImpl dictionaryDAO; + + @Autowired + private CMISDictionaryService cmisDictionaryService; + + @Autowired + private ApplicationContext applicationContext; + + @Autowired + private AlfrescoCmisServiceFactory factory; + + @Autowired + private NodeService nodeService; + + @Autowired + private FileFolderService fileFolderService; + + @Autowired + private ContentService contentService; + + @Autowired + private PersonService personService; + + @Autowired + private MutableAuthenticationService authenticationService; + + private String tenant1; + private String tenant1Username1; + + private void createUser(final String tenant, final String userName, + final String firstName, final String lastName) + { + TenantUtil.runAsSystemTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + if(!authenticationService.authenticationExists(userName)) + { + authenticationService.createAuthentication(userName, "password".toCharArray()); + } + + if(!personService.personExists(userName)) + { + PropertyMap ppOne = new PropertyMap(5); + ppOne.put(ContentModel.PROP_USERNAME, userName); + ppOne.put(ContentModel.PROP_FIRSTNAME, firstName); + ppOne.put(ContentModel.PROP_LASTNAME, lastName); + ppOne.put(ContentModel.PROP_EMAIL, "email@email.com"); + ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle"); + + personService.createPerson(ppOne); + } + + return null; + } + }, tenant); + } + + @Before + public void before() + { + this.tenant1 = "tenant1"; + this.tenant1Username1 = "user" + System.currentTimeMillis(); + + createUser(tenant1, tenant1Username1, tenant1Username1, tenant1Username1); + } + + private void addCustomModelToRepository(M2Model customModel) + throws UnsupportedEncodingException, FileNotFoundException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + customModel.toXML(out); + String modelContent = out.toString("UTF-8"); + NodeRef rootNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); + FileInfo info = fileFolderService.resolveNamePath(rootNodeRef, Arrays.asList("")); + NodeRef modelsNodeRef = info.getNodeRef(); + FileInfo fileInfo = fileFolderService.create( + modelsNodeRef, "contentModel" + System.currentTimeMillis() + ".xml", + ContentModel.TYPE_DICTIONARY_MODEL); + Map properties = new HashMap(); + properties.put(ContentModel.PROP_MODEL_ACTIVE, Boolean.TRUE); + nodeService.setProperties(fileInfo.getNodeRef(), properties); + ContentWriter writer = contentService.getWriter(fileInfo.getNodeRef(), ContentModel.PROP_CONTENT, true); + writer.putContent(modelContent); + } + + @Test + public void test1() + { + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + M2Model customModel = M2Model.createModel( + Thread.currentThread().getContextClassLoader(). + getResourceAsStream("dictionary/dictionarytest_model1.xml")); + addCustomModelToRepository(customModel); + + CallContext context = new SimpleCallContext("user1", "admin", CmisVersion.CMIS_1_1); + + CmisService cmisService = factory.getService(context); + try + { + assertNotNull(cmisService.getTypeDefinition(tenant1, "D:cm:type1", null)); + } + finally + { + cmisService.close(); + } + + return null; + } + }, tenant1Username1, tenant1); + } +} diff --git a/source/test-java/org/alfresco/repo/dictionary/DictionaryDAOTest.java b/source/test-java/org/alfresco/repo/dictionary/DictionaryDAOTest.java new file mode 100644 index 0000000000..9413d83d8a --- /dev/null +++ b/source/test-java/org/alfresco/repo/dictionary/DictionaryDAOTest.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2005-2011 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.dictionary; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.cache.MemoryCache; +import org.alfresco.repo.i18n.StaticMessageLookup; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.tenant.MultiTServiceImpl; +import org.alfresco.repo.tenant.SingleTServiceImpl; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.QName; +import org.junit.Before; +import org.junit.Test; +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * + * @author sglover + * + */ +public class DictionaryDAOTest +{ + public static final String TEST_RESOURCE_MESSAGES = "alfresco/messages/dictionary-messages"; + + private DictionaryService service; + private DictionaryDAOImpl dictionaryDAO; + + @Before + public void setUp() throws Exception + { + // register resource bundles for messages + I18NUtil.registerResourceBundle(TEST_RESOURCE_MESSAGES); + + // Instantiate Dictionary Service + TenantService tenantService = new MultiTServiceImpl(); + + this.dictionaryDAO = new DictionaryDAOImpl(); + dictionaryDAO.setTenantService(tenantService); + + initDictionaryCaches(dictionaryDAO); + + new AuthenticationUtil().afterPropertiesSet(); + + // Populate with appropriate models + DictionaryBootstrap bootstrap = new DictionaryBootstrap(); + List bootstrapModels = new ArrayList(); + bootstrapModels.add("alfresco/model/dictionaryModel.xml"); + bootstrapModels.add("alfresco/model/systemModel.xml"); + bootstrapModels.add("alfresco/model/contentModel.xml"); + List labels = new ArrayList(); + bootstrap.setModels(bootstrapModels); + bootstrap.setLabels(labels); + bootstrap.setDictionaryDAO(dictionaryDAO); + bootstrap.setTenantService(tenantService); + bootstrap.bootstrap(); + + DictionaryComponent component = new DictionaryComponent(); + component.setDictionaryDAO(dictionaryDAO); + component.setMessageLookup(new StaticMessageLookup()); + service = component; + } + + private void initDictionaryCaches(DictionaryDAOImpl dictionaryDAO) + { + dictionaryDAO.setDictionaryRegistryCache(new MemoryCache()); + } + + @Test + public void testBootstrap() + { + TenantService tenantService = new SingleTServiceImpl(); + + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); + dictionaryDAO.setTenantService(tenantService); + initDictionaryCaches(dictionaryDAO); + + DictionaryBootstrap bootstrap = new DictionaryBootstrap(); + List bootstrapModels = new ArrayList(); + + bootstrapModels.add("alfresco/model/dictionaryModel.xml"); + + bootstrap.setModels(bootstrapModels); + bootstrap.setDictionaryDAO(dictionaryDAO); + bootstrap.setTenantService(tenantService); + bootstrap.bootstrap(); + } + + @Test + public void test1() + { + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + M2Model customModel = M2Model.createModel( + Thread.currentThread().getContextClassLoader(). + getResourceAsStream("dictionary/dictionarydaotest_model1.xml")); + dictionaryDAO.putModel(customModel); + assertNotNull(service.getType(ContentModel.TYPE_CONTENT)); + QName qname = QName.createQName("{http://www.alfresco.org/test/dictionarydaotest1/1.0}type1"); + TypeDefinition td = service.getType(qname); + assertNotNull(td); + return null; + } + }, "user1", "tenant1"); + + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + assertNotNull(service.getType(ContentModel.TYPE_CONTENT)); + QName qname = QName.createQName("{http://www.alfresco.org/test/dictionarydaotest1/1.0}type1"); + TypeDefinition td = service.getType(qname); + assertNull(td); + return null; + } + }, "user2", "tenant2"); + } +} diff --git a/source/test-java/org/alfresco/repo/dictionary/DictionaryLoadDAOTest.java b/source/test-java/org/alfresco/repo/dictionary/DictionaryLoadDAOTest.java new file mode 100644 index 0000000000..f27e6c47b5 --- /dev/null +++ b/source/test-java/org/alfresco/repo/dictionary/DictionaryLoadDAOTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2005-2011 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.dictionary; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.alfresco.repo.cache.MemoryCache; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.tenant.MultiTServiceImpl; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; +import org.alfresco.util.DynamicallySizedThreadPoolExecutor; +import org.alfresco.util.TraceableThreadFactory; +import org.alfresco.util.cache.DefaultAsynchronouslyRefreshedCacheRegistry; +import org.junit.Before; +import org.junit.Test; +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * + * @author sglover + * + */ +public class DictionaryLoadDAOTest +{ + public static final String TEST_RESOURCE_MESSAGES = "alfresco/messages/dictionary-messages"; + +// private DictionaryService service; + private DictionaryDAOImpl dictionaryDAO; + + @Before + public void setUp() throws Exception + { + // register resource bundles for messages + I18NUtil.registerResourceBundle(TEST_RESOURCE_MESSAGES); + + // Instantiate Dictionary Service + TenantService tenantService = new MultiTServiceImpl(); + this.dictionaryDAO = new DictionaryDAOImpl(); + dictionaryDAO.setTenantService(tenantService); + +// TenantUtil.runAsUserTenant(new TenantRunAsWork() +// { +// @Override +// public Void doWork() throws Exception +// { +// dictionaryDAO.init(); +// return null; +// } +// }, "user1", "tenant1"); + + initDictionaryCaches(dictionaryDAO, tenantService); + + new AuthenticationUtil().afterPropertiesSet(); + + // Populate with appropriate models + DictionaryBootstrap bootstrap = new DictionaryBootstrap(); + List bootstrapModels = new ArrayList(); + bootstrapModels.add("alfresco/model/dictionaryModel.xml"); + bootstrapModels.add("alfresco/model/systemModel.xml"); + bootstrapModels.add("alfresco/model/contentModel.xml"); + bootstrapModels.add("org/alfresco/repo/security/authentication/userModel.xml"); + bootstrapModels.add("alfresco/model/bpmModel.xml"); + bootstrapModels.add("alfresco/model/wcmModel.xml"); + bootstrapModels.add("alfresco/model/forumModel.xml"); + bootstrapModels.add("alfresco/model/imapModel.xml"); + bootstrapModels.add("alfresco/model/transferModel.xml"); + bootstrapModels.add("alfresco/model/applicationModel.xml"); + bootstrapModels.add("alfresco/model/wcmAppModel.xml"); + bootstrapModels.add("org/alfresco/repo/action/actionModel.xml"); + bootstrapModels.add("org/alfresco/repo/rule/ruleModel.xml"); + bootstrapModels.add("org/alfresco/repo/version/version_model.xml"); + bootstrapModels.add("org/alfresco/repo/version/version2_model.xml"); + bootstrapModels.add("alfresco/model/emailServerModel.xml"); + bootstrapModels.add("alfresco/model/calendarModel.xml"); + bootstrapModels.add("alfresco/model/blogIntegrationModel.xml"); + bootstrapModels.add("alfresco/model/linksModel.xml"); + bootstrapModels.add("alfresco/model/remoteCredentialsModel.xml"); + bootstrapModels.add("alfresco/model/datalistModel.xml"); + bootstrapModels.add("alfresco/model/quickShareModel.xml"); + bootstrapModels.add("alfresco/model/shareUiModel.xml"); + bootstrapModels.add("alfresco/model/siteModel.xml"); + bootstrapModels.add("alfresco/model/publishingModel.xml"); + + List labels = new ArrayList(); + bootstrap.setModels(bootstrapModels); + bootstrap.setLabels(labels); + bootstrap.setDictionaryDAO(dictionaryDAO); + bootstrap.setTenantService(tenantService); + bootstrap.bootstrap(); + } + + private void initDictionaryCaches(DictionaryDAOImpl dictionaryDAO, TenantService tenantService) throws Exception + { + dictionaryDAO.setDictionaryRegistryCache(new MemoryCache()); + +// CompiledModelsCache compiledModelsCache = new CompiledModelsCache(); +// compiledModelsCache.setDictionaryDAO(dictionaryDAO); +// compiledModelsCache.setTenantService(tenantService); +// compiledModelsCache.setRegistry(new DefaultAsynchronouslyRefreshedCacheRegistry()); +// TraceableThreadFactory threadFactory = new TraceableThreadFactory(); +// threadFactory.setThreadDaemon(true); +// threadFactory.setThreadPriority(Thread.NORM_PRIORITY); +// +// ThreadPoolExecutor threadPoolExecutor = new DynamicallySizedThreadPoolExecutor(20, 20, 90, TimeUnit.SECONDS, new LinkedBlockingQueue(), threadFactory, +// new ThreadPoolExecutor.CallerRunsPolicy()); +// compiledModelsCache.setThreadPoolExecutor(threadPoolExecutor); +// dictionaryDAO.setDictionaryRegistryCache(compiledModelsCache); + dictionaryDAO.init(); + } + + @Test + public void test1() + { + TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public Void doWork() throws Exception + { + dictionaryDAO.init(); + + return null; + } + }, "user1", "tenant1"); + } +} diff --git a/source/test-java/org/alfresco/repo/dictionary/DictionaryModelTypeTest.java b/source/test-java/org/alfresco/repo/dictionary/DictionaryModelTypeTest.java index c886c5f261..55ac84c939 100644 --- a/source/test-java/org/alfresco/repo/dictionary/DictionaryModelTypeTest.java +++ b/source/test-java/org/alfresco/repo/dictionary/DictionaryModelTypeTest.java @@ -51,7 +51,6 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.test_category.BaseSpringTestsCategory; -import org.alfresco.test_category.OwnJVMTestsCategory; import org.alfresco.util.BaseAlfrescoSpringTest; import org.alfresco.util.PropertyMap; import org.junit.experimental.categories.Category; @@ -375,9 +374,9 @@ public class DictionaryModelTypeTest extends BaseAlfrescoSpringTest List storeUrlsToValidate = new ArrayList(1); storeUrlsToValidate.add(this.storeRef.toString()); - DictionaryModelType dictionaryModelType = (DictionaryModelType)this.applicationContext.getBean("dictionaryModelType"); - dictionaryModelType.setStoreUrls(storeUrlsToValidate); - + ModelValidatorImpl modelValidator = (ModelValidatorImpl)this.applicationContext.getBean("modelValidator"); + modelValidator.setStoreUrls(storeUrlsToValidate); + DictionaryRepositoryBootstrap bootstrap = new DictionaryRepositoryBootstrap(); bootstrap.setContentService(this.contentService); bootstrap.setDictionaryDAO(this.dictionaryDAO); diff --git a/source/test-java/org/alfresco/repo/dictionary/RepoDictionaryDAOTest.java b/source/test-java/org/alfresco/repo/dictionary/RepoDictionaryDAOTest.java index 9c52b32187..ea5beaad61 100644 --- a/source/test-java/org/alfresco/repo/dictionary/RepoDictionaryDAOTest.java +++ b/source/test-java/org/alfresco/repo/dictionary/RepoDictionaryDAOTest.java @@ -31,10 +31,7 @@ import junit.framework.TestCase; import org.alfresco.model.ContentModel; import org.alfresco.repo.cache.DefaultSimpleCache; -import org.alfresco.repo.cache.NullCache; import org.alfresco.repo.cache.SimpleCache; -import org.alfresco.repo.dictionary.DictionaryDAOImpl.DictionaryRegistry; -import org.alfresco.repo.dictionary.NamespaceDAOImpl.NamespaceRegistry; import org.alfresco.repo.dictionary.constraint.AbstractConstraint; import org.alfresco.repo.dictionary.constraint.ConstraintRegistry; import org.alfresco.repo.dictionary.constraint.RegexConstraint; @@ -89,11 +86,11 @@ public class RepoDictionaryDAOTest extends TestCase // Instantiate Dictionary Service TenantService tenantService = new SingleTServiceImpl(); - NamespaceDAOImpl namespaceDAO = new NamespaceDAOImpl(); - namespaceDAO.setTenantService(tenantService); - initNamespaceCaches(namespaceDAO); +// NamespaceDAOImpl namespaceDAO = new NamespaceDAOImpl(); +// namespaceDAO.setTenantService(tenantService); +// initNamespaceCaches(namespaceDAO); - DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(namespaceDAO); + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); dictionaryDAO.setTenantService(tenantService); initDictionaryCaches(dictionaryDAO); @@ -122,21 +119,21 @@ public class RepoDictionaryDAOTest extends TestCase dictionaryDAO.setDictionaryRegistryCache(dictionaryCache); } - private void initNamespaceCaches(NamespaceDAOImpl namespaceDAO) - { - SimpleCache namespaceCache = new DefaultSimpleCache(11, getClass().getName() + ".namespace"); - namespaceDAO.setNamespaceRegistryCache(namespaceCache); - } +// private void initNamespaceCaches(NamespaceDAOImpl namespaceDAO) +// { +// SimpleCache namespaceCache = new DefaultSimpleCache(11, getClass().getName() + ".namespace"); +// namespaceDAO.setNamespaceRegistryCache(namespaceCache); +// } public void testBootstrap() { - TenantService tenantService = new SingleTServiceImpl(); - NamespaceDAOImpl namespaceDAO = new NamespaceDAOImpl(); - namespaceDAO.setTenantService(tenantService); - initNamespaceCaches(namespaceDAO); + TenantService tenantService = new SingleTServiceImpl(); +// NamespaceDAOImpl namespaceDAO = new NamespaceDAOImpl(); +// namespaceDAO.setTenantService(tenantService); +// initNamespaceCaches(namespaceDAO); - DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(namespaceDAO); + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); dictionaryDAO.setTenantService(tenantService); initDictionaryCaches(dictionaryDAO); @@ -419,18 +416,18 @@ public class RepoDictionaryDAOTest extends TestCase { // source dictionary TenantService tenantService = new SingleTServiceImpl(); - NamespaceDAOImpl namespaceDAO = new NamespaceDAOImpl(); - namespaceDAO.setTenantService(tenantService); - initNamespaceCaches(namespaceDAO); - DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(namespaceDAO); +// NamespaceDAOImpl namespaceDAO = new NamespaceDAOImpl(); +// namespaceDAO.setTenantService(tenantService); +// initNamespaceCaches(namespaceDAO); + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); dictionaryDAO.setTenantService(tenantService); initDictionaryCaches(dictionaryDAO); // destination dictionary - NamespaceDAOImpl namespaceDAO2 = new NamespaceDAOImpl(); - namespaceDAO2.setTenantService(tenantService); - initNamespaceCaches(namespaceDAO2); - DictionaryDAOImpl dictionaryDAO2 = new DictionaryDAOImpl(namespaceDAO2); +// NamespaceDAOImpl namespaceDAO2 = new NamespaceDAOImpl(); +// namespaceDAO2.setTenantService(tenantService); +// initNamespaceCaches(namespaceDAO2); + DictionaryDAOImpl dictionaryDAO2 = new DictionaryDAOImpl(); dictionaryDAO2.setTenantService(tenantService); initDictionaryCaches(dictionaryDAO2); diff --git a/source/test-java/org/alfresco/repo/jscript/ScriptNodeTest.java b/source/test-java/org/alfresco/repo/jscript/ScriptNodeTest.java index 7c87ad3630..d4370b7ee5 100644 --- a/source/test-java/org/alfresco/repo/jscript/ScriptNodeTest.java +++ b/source/test-java/org/alfresco/repo/jscript/ScriptNodeTest.java @@ -32,16 +32,16 @@ import java.util.Map; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.dictionary.DictionaryDAO; -import org.alfresco.repo.dictionary.DictionaryModelType; import org.alfresco.repo.dictionary.DictionaryRepositoryBootstrap; +import org.alfresco.repo.dictionary.ModelValidatorImpl; import org.alfresco.repo.dictionary.RepositoryLocation; import org.alfresco.repo.i18n.MessageService; import org.alfresco.repo.model.Repository; import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.tenant.TenantAdminService; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.security.permissions.PermissionServiceSPI; +import org.alfresco.repo.tenant.TenantAdminService; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.version.VersionableAspect; @@ -67,7 +67,6 @@ import org.alfresco.util.PropertyMap; import org.alfresco.util.test.junitrules.AlfrescoPerson; import org.alfresco.util.test.junitrules.ApplicationContextInit; import org.alfresco.util.test.junitrules.RunAsFullyAuthenticatedRule; -import org.alfresco.util.test.junitrules.RunAsFullyAuthenticatedRule.RunAsUser; import org.alfresco.util.test.junitrules.TemporaryNodes; import org.alfresco.util.test.junitrules.TemporarySites; import org.alfresco.util.test.junitrules.TemporarySites.TestSiteAndMemberInfo; @@ -141,7 +140,7 @@ public class ScriptNodeTest private static TenantAdminService TENANT_ADMIN_SERVICE; private static MessageService MESSAGE_SERVICE; private static TransactionService TRANSACTION_SERVICE; - private static DictionaryModelType DICTIONARY_MODEL_TYPE; + private static ModelValidatorImpl MODEL_VALIDATOR; private static PolicyComponent POLICY_COMPONENT; private static TestSiteAndMemberInfo USER_ONES_TEST_SITE; @@ -180,7 +179,7 @@ public class ScriptNodeTest TENANT_ADMIN_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("tenantAdminService", TenantAdminService.class); MESSAGE_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("messageService", MessageService.class); TRANSACTION_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("transactionComponent", TransactionService.class); - DICTIONARY_MODEL_TYPE = APP_CONTEXT_INIT.getApplicationContext().getBean("dictionaryModelType", DictionaryModelType.class); + MODEL_VALIDATOR = APP_CONTEXT_INIT.getApplicationContext().getBean("modelValidator", ModelValidatorImpl.class); POLICY_COMPONENT = APP_CONTEXT_INIT.getApplicationContext().getBean("policyComponent", PolicyComponent.class); USER_ONES_TEST_SITE = STATIC_TEST_SITES.createTestSiteWithUserPerRole(GUID.generate(), "sitePreset", SiteVisibility.PRIVATE, USER_ONE_NAME); @@ -227,7 +226,7 @@ public class ScriptNodeTest List storeUrlsToValidate = new ArrayList(1); storeUrlsToValidate.add(this.storeRef.toString()); - DICTIONARY_MODEL_TYPE.setStoreUrls(storeUrlsToValidate); + MODEL_VALIDATOR.setStoreUrls(storeUrlsToValidate); RepositoryLocation location = new RepositoryLocation(); location.setStoreProtocol(storeRef.getProtocol()); @@ -253,7 +252,7 @@ public class ScriptNodeTest List storeUrlsToValidate = new ArrayList(1); storeUrlsToValidate.add(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE.toString()); - DICTIONARY_MODEL_TYPE.setStoreUrls(storeUrlsToValidate); + MODEL_VALIDATOR.setStoreUrls(storeUrlsToValidate); RepositoryLocation location = new RepositoryLocation(); location.setStoreProtocol(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE.getProtocol()); diff --git a/source/test-java/org/alfresco/repo/policy/MTPolicyComponentTest.java b/source/test-java/org/alfresco/repo/policy/MTPolicyComponentTest.java index 467fa4ae93..59a474b5b5 100644 --- a/source/test-java/org/alfresco/repo/policy/MTPolicyComponentTest.java +++ b/source/test-java/org/alfresco/repo/policy/MTPolicyComponentTest.java @@ -83,10 +83,10 @@ public class MTPolicyComponentTest extends TestCase when(mockTenantService.getBaseName(any(StoreRef.class))).thenReturn(new StoreRef(BASE_PROTOCOL, BASE_IDENTIFIER)); - NamespaceDAOImpl namespaceDAO = new NamespaceDAOImpl(); - namespaceDAO.setTenantService(mockTenantService); - initNamespaceCaches(namespaceDAO); - DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(namespaceDAO); +// NamespaceDAOImpl namespaceDAO = new NamespaceDAOImpl(); +// namespaceDAO.setTenantService(mockTenantService); +// initNamespaceCaches(namespaceDAO); + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); dictionaryDAO.setTenantService(mockTenantService); initDictionaryCaches(dictionaryDAO); @@ -116,12 +116,12 @@ public class MTPolicyComponentTest extends TestCase dictionaryDAO.setDictionaryRegistryCache(new NullCache()); } - @SuppressWarnings("unchecked") - private void initNamespaceCaches(NamespaceDAOImpl namespaceDAO) - { - // note: unit tested here with null cache - namespaceDAO.setNamespaceRegistryCache(new NullCache()); - } +// @SuppressWarnings("unchecked") +// private void initNamespaceCaches(NamespaceDAOImpl namespaceDAO) +// { +// // note: unit tested here with null cache +// namespaceDAO.setNamespaceRegistryCache(new NullCache()); +// } public void testJavaBehaviour() { diff --git a/source/test-java/org/alfresco/repo/policy/PolicyComponentTest.java b/source/test-java/org/alfresco/repo/policy/PolicyComponentTest.java index 3ecaf01825..5e84294488 100644 --- a/source/test-java/org/alfresco/repo/policy/PolicyComponentTest.java +++ b/source/test-java/org/alfresco/repo/policy/PolicyComponentTest.java @@ -57,10 +57,10 @@ public class PolicyComponentTest extends TestCase { // Instantiate Dictionary Service TenantService tenantService = new SingleTServiceImpl(); - NamespaceDAOImpl namespaceDAO = new NamespaceDAOImpl(); - namespaceDAO.setTenantService(tenantService); - initNamespaceCaches(namespaceDAO); - DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(namespaceDAO); +// NamespaceDAOImpl namespaceDAO = new NamespaceDAOImpl(); +// namespaceDAO.setTenantService(tenantService); +// initNamespaceCaches(namespaceDAO); + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); dictionaryDAO.setTenantService(tenantService); initDictionaryCaches(dictionaryDAO); @@ -88,12 +88,12 @@ public class PolicyComponentTest extends TestCase dictionaryDAO.setDictionaryRegistryCache(new NullCache()); } - @SuppressWarnings("unchecked") - private void initNamespaceCaches(NamespaceDAOImpl namespaceDAO) - { - // note: unit tested here with null cache - namespaceDAO.setNamespaceRegistryCache(new NullCache()); - } +// @SuppressWarnings("unchecked") +// private void initNamespaceCaches(NamespaceDAOImpl namespaceDAO) +// { +// // note: unit tested here with null cache +// namespaceDAO.setNamespaceRegistryCache(new NullCache()); +// } public void testJavaBehaviour() { diff --git a/source/test-java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java b/source/test-java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java index 44a4fc7a67..88aa544b72 100644 --- a/source/test-java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java +++ b/source/test-java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java @@ -26,7 +26,6 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.text.Collator; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -39,11 +38,7 @@ import java.util.Locale; import java.util.Map; import java.util.Random; -import javax.transaction.HeuristicMixedException; -import javax.transaction.HeuristicRollbackException; -import javax.transaction.RollbackException; import javax.transaction.Status; -import javax.transaction.SystemException; import javax.transaction.UserTransaction; import junit.framework.TestCase; @@ -54,7 +49,7 @@ import org.alfresco.repo.dictionary.DictionaryDAO; import org.alfresco.repo.dictionary.DictionaryListener; import org.alfresco.repo.dictionary.DictionaryNamespaceComponent; import org.alfresco.repo.dictionary.M2Model; -import org.alfresco.repo.dictionary.NamespaceDAOImpl; +import org.alfresco.repo.dictionary.NamespaceDAO; import org.alfresco.repo.node.BaseNodeServiceTest; import org.alfresco.repo.node.NodeBulkLoader; import org.alfresco.repo.search.IndexerAndSearcher; @@ -102,16 +97,15 @@ import org.alfresco.service.transaction.TransactionService; import org.alfresco.test_category.OwnJVMTestsCategory; import org.alfresco.util.ApplicationContextHelper; import org.alfresco.util.CachingDateFormat; +import org.alfresco.util.CachingDateFormat.SimpleDateFormatAndResolution; import org.alfresco.util.GUID; import org.alfresco.util.ISO9075; -import org.alfresco.util.CachingDateFormat.SimpleDateFormatAndResolution; import org.alfresco.util.SearchLanguageConversion; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Term; import org.apache.lucene.index.TermDocs; -import org.apache.lucene.index.TermEnum; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.PostgreSQLDialect; import org.junit.experimental.categories.Category; @@ -220,7 +214,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener private NodeRef[] documentOrder; - private NamespaceDAOImpl namespaceDao; + private NamespaceDAO namespaceDao; private Date testDate; @@ -291,7 +285,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); - namespaceDao = (NamespaceDAOImpl) ctx.getBean("namespaceDAO"); + namespaceDao = (NamespaceDAO) ctx.getBean("namespaceDAO"); I18NUtil.setLocale(Locale.UK); @@ -310,7 +304,7 @@ public class ADMLuceneTest extends TestCase implements DictionaryListener InputStream modelStream = cl.getResourceAsStream("org/alfresco/repo/search/impl/lucene/LuceneTest_model.xml"); assertNotNull(modelStream); model = M2Model.createModel(modelStream); - dictionaryDAO.register(this); + dictionaryDAO.registerListener(this); dictionaryDAO.reset(); assertNotNull(dictionaryDAO.getClass(testSuperType)); diff --git a/source/test-java/org/alfresco/repo/search/impl/querymodel/impl/db/DBQueryTest.java b/source/test-java/org/alfresco/repo/search/impl/querymodel/impl/db/DBQueryTest.java index e9b42e3305..a09e4f959d 100644 --- a/source/test-java/org/alfresco/repo/search/impl/querymodel/impl/db/DBQueryTest.java +++ b/source/test-java/org/alfresco/repo/search/impl/querymodel/impl/db/DBQueryTest.java @@ -42,7 +42,7 @@ import org.alfresco.repo.dictionary.DictionaryDAO; import org.alfresco.repo.dictionary.DictionaryListener; import org.alfresco.repo.dictionary.DictionaryNamespaceComponent; import org.alfresco.repo.dictionary.M2Model; -import org.alfresco.repo.dictionary.NamespaceDAOImpl; +import org.alfresco.repo.dictionary.NamespaceDAO; import org.alfresco.repo.node.BaseNodeServiceTest; import org.alfresco.repo.search.impl.lucene.ADMLuceneTest.UnknownDataType; import org.alfresco.repo.security.authentication.AuthenticationComponent; @@ -130,7 +130,7 @@ public class DBQueryTest implements DictionaryListener private DictionaryDAO dictionaryDAO; - private NamespaceDAOImpl namespaceDao; + private NamespaceDAO namespaceDao; private ServiceRegistry serviceRegistry; @@ -236,7 +236,7 @@ public class DBQueryTest implements DictionaryListener retryingTransactionHelper = (RetryingTransactionHelper) ctx.getBean("retryingTransactionHelper"); tenantService = (TenantService) ctx.getBean("tenantService"); serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); - namespaceDao = (NamespaceDAOImpl) ctx.getBean("namespaceDAO"); + namespaceDao = (NamespaceDAO) ctx.getBean("namespaceDAO"); authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent"); contentService = (ContentService) ctx.getBean("contentService"); @@ -250,7 +250,7 @@ public class DBQueryTest implements DictionaryListener InputStream modelStream = cl.getResourceAsStream("org/alfresco/repo/search/impl/MetadataQueryTest_model.xml"); assertNotNull(modelStream); model = M2Model.createModel(modelStream); - dictionaryDAO.register(this); + dictionaryDAO.registerListener(this); dictionaryDAO.reset(); assertNotNull(dictionaryDAO.getClass(TEST_SUPER_CONTENT_TYPE)); } diff --git a/source/test-resources/dictionary/dictionarydaotest_model1.properties b/source/test-resources/dictionary/dictionarydaotest_model1.properties new file mode 100644 index 0000000000..7ff0b4b99c --- /dev/null +++ b/source/test-resources/dictionary/dictionarydaotest_model1.properties @@ -0,0 +1,21 @@ +test_dictionarydaotest.description=Model Description + +test_dictionarydaotest.class.test_base.title=Base Title +test_dictionarydaotest.class.test_base.description=Base Description + +test_dictionarydaotest.property.test_prop1.title=Prop1 Title +test_dictionarydaotest.property.test_prop1.description=Prop1 Description + +test_dictionarydaotest.association.test_assoc1.title=Assoc1 Title +test_dictionarydaotest.association.test_assoc1.description=Assoc1 Description + +test_dictionarydaotest.datatype.test_datatype.analyzer=Datatype Analyser + +listconstraint.test_list1.ABC=ABC display +listconstraint.test_list1.DEF=DEF display +listconstraint.test_list1.VALUE\ WITH\ SPACES=VALUE WITH SPACES display + +listconstraint.test_inlineConstraint.ALPHA=ALPHA display +listconstraint.test_inlineConstraint.BETA=BETA display +listconstraint.test_inlineConstraint.GAMMA,\ DELTA=GAMMA, DELTA display +# Intentionally no localisation for OMEGA. diff --git a/source/test-resources/dictionary/dictionarydaotest_model1.xml b/source/test-resources/dictionary/dictionarydaotest_model1.xml new file mode 100644 index 0000000000..8b4206b22c --- /dev/null +++ b/source/test-resources/dictionary/dictionarydaotest_model1.xml @@ -0,0 +1,85 @@ + + + Alfresco Content Model + Alfresco + 2005-05-30 + 1.0 + + + + + + + + + + + + + + Base + Type 1 + cm:content + + + + d:text + true + + + + + + + + true + false + + + cm:content + false + true + + + + + true + true + + + cm:content + false + false + + fred + true + + + + + daotest1:aspect1 + + + + + + + Aspect1 + Aspect1 + + + + + d:int + true + true + + true + false + + + + + + + diff --git a/source/test-resources/dictionary/dictionarytest_model1.properties b/source/test-resources/dictionary/dictionarytest_model1.properties new file mode 100644 index 0000000000..7ff0b4b99c --- /dev/null +++ b/source/test-resources/dictionary/dictionarytest_model1.properties @@ -0,0 +1,21 @@ +test_dictionarydaotest.description=Model Description + +test_dictionarydaotest.class.test_base.title=Base Title +test_dictionarydaotest.class.test_base.description=Base Description + +test_dictionarydaotest.property.test_prop1.title=Prop1 Title +test_dictionarydaotest.property.test_prop1.description=Prop1 Description + +test_dictionarydaotest.association.test_assoc1.title=Assoc1 Title +test_dictionarydaotest.association.test_assoc1.description=Assoc1 Description + +test_dictionarydaotest.datatype.test_datatype.analyzer=Datatype Analyser + +listconstraint.test_list1.ABC=ABC display +listconstraint.test_list1.DEF=DEF display +listconstraint.test_list1.VALUE\ WITH\ SPACES=VALUE WITH SPACES display + +listconstraint.test_inlineConstraint.ALPHA=ALPHA display +listconstraint.test_inlineConstraint.BETA=BETA display +listconstraint.test_inlineConstraint.GAMMA,\ DELTA=GAMMA, DELTA display +# Intentionally no localisation for OMEGA. diff --git a/source/test-resources/dictionary/dictionarytest_model1.xml b/source/test-resources/dictionary/dictionarytest_model1.xml new file mode 100644 index 0000000000..084922829d --- /dev/null +++ b/source/test-resources/dictionary/dictionarytest_model1.xml @@ -0,0 +1,85 @@ + + + Alfresco Content Model + Alfresco + 2005-05-30 + 1.0 + + + + + + + + + + + + + + Base + Type 1 + cm:content + + + + d:text + true + + + + + + + + true + false + + + cm:content + false + true + + + + + true + true + + + cm:content + false + false + + fred + true + + + + + dictionarytest1:aspect1 + + + + + + + Aspect1 + Aspect1 + + + + + d:int + true + true + + true + false + + + + + + +