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
This commit is contained in:
Jan Vonka 2008-02-12 17:28:15 +00:00
parent 1633ef3132
commit cdd9e51a75
10 changed files with 204 additions and 109 deletions

View File

@ -94,7 +94,7 @@
<bean id="systemInfoBootstrap" parent="systemInfoImporter">
</bean>
<bean id="userBootstrap" parent="userStoreImporter">
<bean id="userBootstrap" parent="userStoreImporter" singleton="false">
<property name="bootstrapViews">
<list>
<props>
@ -117,7 +117,7 @@
</property>
</bean>
<bean id="systemBootstrap" parent="systemStoreImporter">
<bean id="systemBootstrap" parent="systemStoreImporter" singleton="false">
<property name="bootstrapViews">
<list>
<props>
@ -132,7 +132,7 @@
</property>
</bean>
<bean id="versionBootstrap" parent="versionStoreImporter">
<bean id="versionBootstrap" parent="versionStoreImporter" singleton="false">
<property name="bootstrapViews">
<list>
<props>
@ -143,7 +143,7 @@
</property>
</bean>
<bean id="spacesArchiveBootstrap" parent="spacesArchiveStoreImporter">
<bean id="spacesArchiveBootstrap" parent="spacesArchiveStoreImporter" singleton="false">
<property name="bootstrapViews">
<list>
<props>
@ -154,11 +154,11 @@
</property>
</bean>
<bean id="spacesModelsBootstrap" parent="storeImporter">
<bean id="spacesModelsBootstrap" parent="storeImporter" singleton="false">
<!-- NOOP for fresh bootstrap (will skip store creation) - provides ordering when performing a repo restore (bootstrap import) -->
</bean>
<bean id="spacesBootstrap" parent="spacesStoreImporter">
<bean id="spacesBootstrap" parent="spacesStoreImporter" singleton="false">
<property name="bootstrapViews">
<list>
<props>

View File

@ -23,8 +23,8 @@
<property name="tenantFileContentStore" ref="tenantFileContentStore"/>
<property name="workflowService" ref="WorkflowService"/>
<property name="repositoryExporterService" ref="repositoryExporterComponent"/>
<property name="workflowDeployer" ref="workflowBootstrap"/>
<property name="workflowDeployer" ref="workflowBootstrap"/>
<property name="moduleService" ref="moduleService"/>
</bean>

View File

@ -11,14 +11,16 @@
<property name="serviceRegistry" ref="ServiceRegistry" />
<property name="descriptorService" ref="DescriptorService" />
<property name="authenticationComponent" ref="AuthenticationComponent" />
<property name="registryService" ref="RegistryService" />
<property name="registryService" ref="RegistryService" />
<property name="tenantDeployerService" ref="tenantAdminService" />
</bean>
<!-- Parent bean for beans derived from AbstractModuleComponent -->
<bean id="module.baseComponent" abstract="true" init-method="init">
<property name="serviceRegistry" ref="ServiceRegistry" />
<property name="authenticationComponent" ref="AuthenticationComponent" />
<property name="moduleService" ref="ModuleService" />
<property name="moduleService" ref="ModuleService" />
<property name="tenantDeployerService" ref="tenantAdminService" />
</bean>
<!-- Import of installed modules -->

View File

@ -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(

View File

@ -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<ModuleComponent> dependsOn;
/** Defaults to <tt>true</tt> */
private boolean executeOnceOnly;
private boolean executed;
private Map<String, Boolean> executed;
public AbstractModuleComponent()
{
@ -75,7 +79,7 @@ public abstract class AbstractModuleComponent implements ModuleComponent, BeanNa
appliesToVersion = VersionNumber.VERSION_BIG;
dependsOn = new ArrayList<ModuleComponent>(0);
executeOnceOnly = true;
executed = false;
executed = new HashMap<String, Boolean>(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);
}
}
}

View File

@ -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<String, Map<String, ModuleComponent>> 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<Object>()
{
TransactionService transactionService = serviceRegistry.getTransactionService();
authenticationComponent.setSystemUserAsCurrentUser();
// Get all the modules
List<ModuleDetails> modules = moduleService.getAllModules();
loggerService.info(I18NUtil.getMessage(MSG_FOUND_MODULES, modules.size()));
// Process each module in turn. Ordering is not important.
final Set<ModuleComponent> executedComponents = new HashSet<ModuleComponent>(10);
final Set<String> startedModules = new HashSet<String>(2);
for (final ModuleDetails module : modules)
public Object doWork() throws Exception
{
RetryingTransactionCallback<Object> startModuleWork = new RetryingTransactionCallback<Object>()
{
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<ModuleDetails> modules = moduleService.getAllModules();
loggerService.info(I18NUtil.getMessage(MSG_FOUND_MODULES, modules.size()));
// Process each module in turn. Ordering is not important.
final Map<String, Set<ModuleComponent>> mapExecutedComponents = new HashMap<String, Set<ModuleComponent>>(1);
final Map<String, Set<String>> mapStartedModules = new HashMap<String, Set<String>>(1);
mapExecutedComponents.put(tenantDomainCtx, new HashSet<ModuleComponent>(10));
mapStartedModules.put(tenantDomainCtx, new HashSet<String>(2));
final List<Tenant> tenants;
if (tenantDeployerService.isEnabled() && (tenantDomainCtx.equals(TenantService.DEFAULT_DOMAIN)))
{
tenants = tenantDeployerService.getAllTenants();
for (Tenant tenant : tenants)
{
mapExecutedComponents.put(tenant.getTenantDomain(), new HashSet<ModuleComponent>(10));
mapStartedModules.put(tenant.getTenantDomain(), new HashSet<String>(2));
}
}
else
{
tenants = null;
}
for (final ModuleDetails module : modules)
{
RetryingTransactionCallback<Object> startModuleWork = new RetryingTransactionCallback<Object>()
{
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<Object>()
{
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<Object>()
{
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<Object>()
{
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));
}
/**

View File

@ -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)
*/

View File

@ -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<TenantDeployer> tenantDeployers = new ArrayList<TenantDeployer>();
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<Object>()
{
public Object doWork()
{
workflowDeployer.init();
return null;
}
}, getSystemUser(tenantDomain));
logger.info("Tenant workflows bootstrapped: " + tenantDomain);
}
/**
* @see TenantAdminService.deleteTenant()

View File

@ -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<Tenant> getAllTenants();

View File

@ -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"))