From cdd9e51a756e1de1033958ede9f0feec90b4d50c Mon Sep 17 00:00:00 2001 From: Jan Vonka Date: Tue, 12 Feb 2008 17:28:15 +0000 Subject: [PATCH] MT - initial AMP support (AR-2063, ACT-1280) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@8262 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/bootstrap-context.xml | 12 +- .../extension/mt/mt-admin-context.xml.sample | 4 +- config/alfresco/module-context.xml | 6 +- .../admin/registry/RegistryServiceImpl.java | 4 +- .../repo/module/AbstractModuleComponent.java | 25 ++- .../repo/module/ModuleComponentHelper.java | 161 +++++++++++++----- .../repo/module/ModuleServiceImpl.java | 8 +- .../repo/tenant/MultiTAdminServiceImpl.java | 54 ++++-- .../repo/tenant/TenantAdminService.java | 4 +- .../repo/tenant/TenantInterpreter.java | 35 ---- 10 files changed, 204 insertions(+), 109 deletions(-) diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml index 9f9dcfdf64..b5017e9377 100644 --- a/config/alfresco/bootstrap-context.xml +++ b/config/alfresco/bootstrap-context.xml @@ -94,7 +94,7 @@ - + @@ -117,7 +117,7 @@ - + @@ -132,7 +132,7 @@ - + @@ -143,7 +143,7 @@ - + @@ -154,11 +154,11 @@ - + - + diff --git a/config/alfresco/extension/mt/mt-admin-context.xml.sample b/config/alfresco/extension/mt/mt-admin-context.xml.sample index c31ff643fc..318d3bee71 100644 --- a/config/alfresco/extension/mt/mt-admin-context.xml.sample +++ b/config/alfresco/extension/mt/mt-admin-context.xml.sample @@ -23,8 +23,8 @@ - - + + diff --git a/config/alfresco/module-context.xml b/config/alfresco/module-context.xml index e9832be446..910bfdd2a2 100644 --- a/config/alfresco/module-context.xml +++ b/config/alfresco/module-context.xml @@ -11,14 +11,16 @@ - + + - + + diff --git a/source/java/org/alfresco/repo/admin/registry/RegistryServiceImpl.java b/source/java/org/alfresco/repo/admin/registry/RegistryServiceImpl.java index 0e0c3c44fe..c510e2417e 100644 --- a/source/java/org/alfresco/repo/admin/registry/RegistryServiceImpl.java +++ b/source/java/org/alfresco/repo/admin/registry/RegistryServiceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -131,7 +131,7 @@ public class RegistryServiceImpl implements RegistryService { NodeRef registryRootNodeRef = null; // Ensure that the registry root node is present - ResultSet rs = searchService.query(registryStoreRef, SearchService.LANGUAGE_XPATH, registryRootPath); + ResultSet rs = searchService.query(registryStoreRef, SearchService.LANGUAGE_LUCENE, "PATH:\"" + registryRootPath + "\""); if (rs.length() == 0) { throw new AlfrescoRuntimeException( diff --git a/source/java/org/alfresco/repo/module/AbstractModuleComponent.java b/source/java/org/alfresco/repo/module/AbstractModuleComponent.java index 18636ed5ee..1cc6f6c65a 100644 --- a/source/java/org/alfresco/repo/module/AbstractModuleComponent.java +++ b/source/java/org/alfresco/repo/module/AbstractModuleComponent.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -25,11 +25,14 @@ package org.alfresco.repo.module; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.i18n.I18NUtil; import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.repo.tenant.TenantDeployerService; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.module.ModuleService; import org.alfresco.util.EqualsHelper; @@ -56,6 +59,7 @@ public abstract class AbstractModuleComponent implements ModuleComponent, BeanNa protected ServiceRegistry serviceRegistry; protected AuthenticationComponent authenticationComponent; protected ModuleService moduleService; + private TenantDeployerService tenantDeployerService; private String moduleId; private String name; @@ -66,7 +70,7 @@ public abstract class AbstractModuleComponent implements ModuleComponent, BeanNa private List dependsOn; /** Defaults to true */ private boolean executeOnceOnly; - private boolean executed; + private Map executed; public AbstractModuleComponent() { @@ -75,7 +79,7 @@ public abstract class AbstractModuleComponent implements ModuleComponent, BeanNa appliesToVersion = VersionNumber.VERSION_BIG; dependsOn = new ArrayList(0); executeOnceOnly = true; - executed = false; + executed = new HashMap(1); } /** @@ -153,6 +157,11 @@ public abstract class AbstractModuleComponent implements ModuleComponent, BeanNa { this.serviceRegistry = serviceRegistry; } + + public void setTenantDeployerService(TenantDeployerService tenantDeployerService) + { + this.tenantDeployerService = tenantDeployerService; + } /** * {@inheritDoc} @@ -332,7 +341,13 @@ public abstract class AbstractModuleComponent implements ModuleComponent, BeanNa public final synchronized void execute() { // ensure that this has not been executed already - if (executed) + String tenantDomain = tenantDeployerService.getCurrentUserDomain(); + if (! executed.containsKey(tenantDomain)) + { + executed.put(tenantDomain, false); + } + + if (executed.get(tenantDomain)) { throw AlfrescoRuntimeException.create(ERR_ALREADY_EXECUTED, moduleId, name); } @@ -350,7 +365,7 @@ public abstract class AbstractModuleComponent implements ModuleComponent, BeanNa finally { // There are no second chances - executed = true; + executed.put(tenantDomain, true); } } } diff --git a/source/java/org/alfresco/repo/module/ModuleComponentHelper.java b/source/java/org/alfresco/repo/module/ModuleComponentHelper.java index a70b76dda9..29ee3d6cbd 100644 --- a/source/java/org/alfresco/repo/module/ModuleComponentHelper.java +++ b/source/java/org/alfresco/repo/module/ModuleComponentHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -33,13 +33,16 @@ import java.util.List; import java.util.Map; import java.util.Set; -import net.sf.acegisecurity.Authentication; - import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.i18n.I18NUtil; import org.alfresco.repo.admin.registry.RegistryKey; import org.alfresco.repo.admin.registry.RegistryService; import org.alfresco.repo.security.authentication.AuthenticationComponent; +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.TenantDeployerService; +import org.alfresco.repo.tenant.TenantService; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.module.ModuleDependency; @@ -89,6 +92,7 @@ public class ModuleComponentHelper private AuthenticationComponent authenticationComponent; private RegistryService registryService; private ModuleService moduleService; + private TenantDeployerService tenantDeployerService; private Map> componentsByNameByModule; /** Default constructor */ @@ -136,6 +140,11 @@ public class ModuleComponentHelper { this.moduleService = moduleService; } + + public void setTenantDeployerService(TenantDeployerService tenantDeployerService) + { + this.tenantDeployerService = tenantDeployerService; + } /** * Add a managed module component to the registry of components. These will be controlled @@ -197,47 +206,123 @@ public class ModuleComponentHelper PropertyCheck.mandatory(this, "authenticationComponent", authenticationComponent); PropertyCheck.mandatory(this, "registryService", registryService); PropertyCheck.mandatory(this, "moduleService", moduleService); + PropertyCheck.mandatory(this, "tenantDeployerService", tenantDeployerService); /* * Ensure transactionality and the correct authentication */ - // Get the current authentication - Authentication authentication = authenticationComponent.getCurrentAuthentication(); - try + + // Note: for system bootstrap this will be the default domain, else tenant domain for tenant create/import + final String tenantDomainCtx = tenantDeployerService.getCurrentUserDomain(); + + AuthenticationUtil.runAs(new RunAsWork() { - TransactionService transactionService = serviceRegistry.getTransactionService(); - authenticationComponent.setSystemUserAsCurrentUser(); - // Get all the modules - List modules = moduleService.getAllModules(); - loggerService.info(I18NUtil.getMessage(MSG_FOUND_MODULES, modules.size())); - // Process each module in turn. Ordering is not important. - final Set executedComponents = new HashSet(10); - final Set startedModules = new HashSet(2); - for (final ModuleDetails module : modules) + public Object doWork() throws Exception { - RetryingTransactionCallback startModuleWork = new RetryingTransactionCallback() - { - public Object execute() throws Exception - { - startModule(module, startedModules, executedComponents); - return null; - } - }; - transactionService.getRetryingTransactionHelper().doInTransaction(startModuleWork); + try + { + TransactionService transactionService = serviceRegistry.getTransactionService(); + + // Get all the modules + List modules = moduleService.getAllModules(); + loggerService.info(I18NUtil.getMessage(MSG_FOUND_MODULES, modules.size())); + + // Process each module in turn. Ordering is not important. + final Map> mapExecutedComponents = new HashMap>(1); + final Map> mapStartedModules = new HashMap>(1); + + mapExecutedComponents.put(tenantDomainCtx, new HashSet(10)); + mapStartedModules.put(tenantDomainCtx, new HashSet(2)); + + final List tenants; + if (tenantDeployerService.isEnabled() && (tenantDomainCtx.equals(TenantService.DEFAULT_DOMAIN))) + { + tenants = tenantDeployerService.getAllTenants(); + for (Tenant tenant : tenants) + { + mapExecutedComponents.put(tenant.getTenantDomain(), new HashSet(10)); + mapStartedModules.put(tenant.getTenantDomain(), new HashSet(2)); + } + } + else + { + tenants = null; + } + + for (final ModuleDetails module : modules) + { + RetryingTransactionCallback startModuleWork = new RetryingTransactionCallback() + { + public Object execute() throws Exception + { + startModule(module, mapStartedModules.get(tenantDomainCtx), mapExecutedComponents.get(tenantDomainCtx)); + + if (tenants != null) + { + for (Tenant tenant : tenants) + { + final String tenantDomain = tenant.getTenantDomain(); + AuthenticationUtil.runAs(new RunAsWork() + { + public Object doWork() throws Exception + { + startModule(module, mapStartedModules.get(tenantDomain), mapExecutedComponents.get(tenantDomain)); + return null; + } + }, tenantDeployerService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantDomain)); + } + } + + return null; + } + }; + transactionService.getRetryingTransactionHelper().doInTransaction(startModuleWork); + } + + // Check for missing modules. + checkForMissingModules(); + + if (tenants != null) + { + for (Tenant tenant : tenants) + { + AuthenticationUtil.runAs(new RunAsWork() + { + public Object doWork() throws Exception + { + checkForMissingModules(); + return null; + } + }, tenantDeployerService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenant.getTenantDomain())); + } + } + + // Check that all components where executed, or considered for execution + checkForOrphanComponents(mapExecutedComponents.get(tenantDomainCtx)); + + if (tenants != null) + { + for (Tenant tenant : tenants) + { + final String tenantDomain = tenant.getTenantDomain(); + AuthenticationUtil.runAs(new RunAsWork() + { + public Object doWork() throws Exception + { + checkForOrphanComponents(mapExecutedComponents.get(tenantDomain)); + return null; + } + }, tenantDeployerService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantDomain)); + } + } + } + catch (Throwable e) + { + throw new AlfrescoRuntimeException("Failed to start modules", e); + } + + return null; } - - // Check for missing modules. - checkForMissingModules(); - - // Check that all components where executed, or considered for execution - checkForOrphanComponents(executedComponents); - - // Restore the original authentication - authenticationComponent.setCurrentAuthentication(authentication); - } - catch (Throwable e) - { - throw new AlfrescoRuntimeException("Failed to start modules", e); - } + }, tenantDeployerService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantDomainCtx)); } /** diff --git a/source/java/org/alfresco/repo/module/ModuleServiceImpl.java b/source/java/org/alfresco/repo/module/ModuleServiceImpl.java index 8d99e02f7f..26bbc46f2d 100644 --- a/source/java/org/alfresco/repo/module/ModuleServiceImpl.java +++ b/source/java/org/alfresco/repo/module/ModuleServiceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -37,6 +37,7 @@ import java.util.Properties; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.repo.admin.registry.RegistryService; import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.repo.tenant.TenantDeployerService; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.module.ModuleDetails; import org.alfresco.service.cmr.module.ModuleService; @@ -114,6 +115,11 @@ public class ModuleServiceImpl implements ModuleService this.moduleComponentHelper.setRegistryService(registryService); } + public void setTenantDeployerService(TenantDeployerService tenantDeployerService) + { + this.moduleComponentHelper.setTenantDeployerService(tenantDeployerService); + } + /** * @see ModuleComponentHelper#registerComponent(ModuleComponent) */ diff --git a/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java b/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java index 738424c27f..a8e705f140 100755 --- a/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java +++ b/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -55,6 +55,7 @@ import org.alfresco.repo.usage.UserUsageTrackingComponent; import org.alfresco.repo.workflow.WorkflowDeployer; import org.alfresco.service.cmr.admin.RepoAdminService; import org.alfresco.service.cmr.attributes.AttributeService; +import org.alfresco.service.cmr.module.ModuleService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.view.RepositoryExporterService; import org.alfresco.service.cmr.workflow.WorkflowDefinition; @@ -62,6 +63,7 @@ import org.alfresco.service.cmr.workflow.WorkflowService; import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.AbstractLifecycleBean; import org.alfresco.util.ParameterCheck; +import org.alfresco.util.PropertyCheck; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationEvent; @@ -89,6 +91,7 @@ public class MultiTAdminServiceImpl extends AbstractLifecycleBean implements Ten private WorkflowService workflowService; private RepositoryExporterService repositoryExporterService; private WorkflowDeployer workflowDeployer; + private ModuleService moduleService; /* * Tenant domain/ids are unique strings that are case-insensitive. Tenant ids must be valid filenames. @@ -181,6 +184,10 @@ public class MultiTAdminServiceImpl extends AbstractLifecycleBean implements Ten this.workflowDeployer = workflowDeployer; } + public void setModuleService(ModuleService moduleService) + { + this.moduleService = moduleService; + } public static final String PROTOCOL_STORE_USER = "user"; public static final String PROTOCOL_STORE_WORKSPACE = "workspace"; @@ -201,9 +208,28 @@ public class MultiTAdminServiceImpl extends AbstractLifecycleBean implements Ten private List tenantDeployers = new ArrayList(); + protected void checkProperties() + { + PropertyCheck.mandatory(this, "NodeService", nodeService); + PropertyCheck.mandatory(this, "DictionaryComponent", dictionaryComponent); + PropertyCheck.mandatory(this, "RepoAdminService", repoAdminService); + PropertyCheck.mandatory(this, "TransactionService", transactionService); + PropertyCheck.mandatory(this, "TenantService", tenantService); + PropertyCheck.mandatory(this, "AttributeService", attributeService); + PropertyCheck.mandatory(this, "PasswordEncoder", passwordEncoder); + PropertyCheck.mandatory(this, "TenantFileContentStore", tenantFileContentStore); + PropertyCheck.mandatory(this, "WorkflowService", workflowService); + PropertyCheck.mandatory(this, "RepositoryExporterService", repositoryExporterService); + PropertyCheck.mandatory(this, "WorkflowDeployer", workflowDeployer); + + PropertyCheck.mandatory(this, "ModuleService - see updated alfresco/extension/mt/mt-admin-context.xml.sample", moduleService); + } + @Override protected void onBootstrap(ApplicationEvent event) { + checkProperties(); + // initialise the tenant admin service and status of tenants (using attribute service) // note: this requires that the repository schema has already been initialised @@ -314,6 +340,12 @@ public class MultiTAdminServiceImpl extends AbstractLifecycleBean implements Ten tenantDeployer.onEnableTenant(); } + // bootstrap workflows + workflowDeployer.init(); + + // bootstrap modules (if any) + moduleService.startModules(); + return null; } }, getSystemUser(tenantDomain)); @@ -366,6 +398,12 @@ public class MultiTAdminServiceImpl extends AbstractLifecycleBean implements Ten tenantDeployer.onEnableTenant(); } + // bootstrap workflows + workflowDeployer.init(); + + // bootstrap modules (if any) + moduleService.startModules(); + return null; } }, getSystemUser(tenantDomain)); @@ -528,20 +566,6 @@ public class MultiTAdminServiceImpl extends AbstractLifecycleBean implements Ten { return new Tenant(tenantDomain, isEnabledTenant(tenantDomain), getRootContentStoreDir(tenantDomain)); } - - public void bootstrapWorkflows(String tenantDomain) - { - AuthenticationUtil.runAs(new RunAsWork() - { - public Object doWork() - { - workflowDeployer.init(); - return null; - } - }, getSystemUser(tenantDomain)); - - logger.info("Tenant workflows bootstrapped: " + tenantDomain); - } /** * @see TenantAdminService.deleteTenant() diff --git a/source/java/org/alfresco/repo/tenant/TenantAdminService.java b/source/java/org/alfresco/repo/tenant/TenantAdminService.java index 62a8a04bb8..b5ea072f6c 100755 --- a/source/java/org/alfresco/repo/tenant/TenantAdminService.java +++ b/source/java/org/alfresco/repo/tenant/TenantAdminService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 Alfresco Software Limited. + * Copyright (C) 2005-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -47,8 +47,6 @@ public interface TenantAdminService extends TenantDeployerService public boolean existsTenant(String tenantDomain); - public void bootstrapWorkflows(String tenantDomain); - public void deleteTenant(String tenantDomain); public List getAllTenants(); diff --git a/source/java/org/alfresco/repo/tenant/TenantInterpreter.java b/source/java/org/alfresco/repo/tenant/TenantInterpreter.java index c348aa0d54..dd7e84954a 100755 --- a/source/java/org/alfresco/repo/tenant/TenantInterpreter.java +++ b/source/java/org/alfresco/repo/tenant/TenantInterpreter.java @@ -198,26 +198,6 @@ public class TenantInterpreter extends BaseInterpreter return "Syntax Error, try 'help'.\n"; } - String newTenant = new String(command[1]).toLowerCase(); - String tenantAdminRawPassword = new String(command[2]); - - String createTenantArgs = newTenant + " " + tenantAdminRawPassword; - if (command.length == 4) - { - createTenantArgs = createTenantArgs + " " + new String(command[3]); - } - - out.print(executeCommand("createWithoutWorkflows " + createTenantArgs)); - out.print(executeCommand("bootstrapWorkflows " + newTenant)); - } - - else if (command[0].equals("createWithoutWorkflows")) - { - if ((command.length != 3) && (command.length != 4)) - { - return "Syntax Error, try 'help'.\n"; - } - String newTenant = new String(command[1]).toLowerCase(); char[] tenantAdminRawPassword = new String(command[2]).toCharArray(); String rootContentStoreDir = null; @@ -231,20 +211,6 @@ public class TenantInterpreter extends BaseInterpreter out.println("created tenant: " + newTenant); } - else if (command[0].equals("bootstrapWorkflows")) - { - if (command.length != 2) - { - return "Syntax Error, try 'help'.\n"; - } - - String newTenant = new String(command[1]).toLowerCase(); - - tenantAdminService.bootstrapWorkflows(newTenant); - - out.println("bootstrap workflows deployed for tenant: " + newTenant); - } - else if (command[0].equals("import")) { if ((command.length != 3) && (command.length != 4)) @@ -264,7 +230,6 @@ public class TenantInterpreter extends BaseInterpreter tenantAdminService.importTenant(newTenant, directorySource, rootContentStoreDir); out.println("imported tenant: " + newTenant); - out.print(executeCommand("bootstrapWorkflows " + newTenant)); } else if (command[0].equals("export"))