mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Merged DEV\EXTENSIONS to HEAD
svn merge svn://svn.alfresco.com:3691/alfresco/BRANCHES/DEV/EXTENSIONS@4868 svn://svn.alfresco.com:3691/alfresco/BRANCHES/DEV/EXTENSIONS@4869 . svn merge svn://svn.alfresco.com:3691/alfresco/BRANCHES/DEV/EXTENSIONS@4904 svn://svn.alfresco.com:3691/alfresco/BRANCHES/DEV/EXTENSIONS@4938 . Module management support Modularization of Records Management git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@4956 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
342
source/java/org/alfresco/repo/module/ModuleComponentHelper.java
Normal file
342
source/java/org/alfresco/repo/module/ModuleComponentHelper.java
Normal file
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.repo.module;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
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.transaction.TransactionUtil;
|
||||
import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.module.ModuleDetails;
|
||||
import org.alfresco.service.cmr.module.ModuleService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.alfresco.util.VersionNumber;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Helper class to split up some of the code for managing module components. This class handles
|
||||
* the execution of the module components.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class ModuleComponentHelper
|
||||
{
|
||||
public static final String URI_MODULES_1_0 = "http://www.alfresco.org/system/modules/1.0";
|
||||
private static final String REGISTRY_PATH_MODULES = "modules";
|
||||
private static final String REGISTRY_PROPERTY_INSTALLED_VERSION = "installedVersion";
|
||||
private static final String REGISTRY_PROPERTY_CURRENT_VERSION = "currentVersion";
|
||||
private static final String REGISTRY_PATH_COMPONENTS = "components";
|
||||
private static final String REGISTRY_PROPERTY_EXECUTION_DATE = "executionDate";
|
||||
|
||||
private static final String MSG_FOUND_MODULES = "module.msg.found_modules";
|
||||
private static final String MSG_STARTING = "module.msg.starting";
|
||||
private static final String MSG_INSTALLING = "module.msg.installing";
|
||||
private static final String MSG_UPGRADING = "module.msg.upgrading";
|
||||
private static final String ERR_NO_DOWNGRADE = "module.err.downgrading_not_supported";
|
||||
private static final String ERR_COMPONENT_ALREADY_REGISTERED = "module.err.component_already_registered";
|
||||
|
||||
private static Log logger = LogFactory.getLog(ModuleComponentHelper.class);
|
||||
private static Log loggerService = LogFactory.getLog(ModuleServiceImpl.class);
|
||||
|
||||
private ServiceRegistry serviceRegistry;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
private RegistryService registryService;
|
||||
private ModuleService moduleService;
|
||||
private Map<String, Map<String, ModuleComponent>> componentsByNameByModule;
|
||||
|
||||
/** Default constructor */
|
||||
public ModuleComponentHelper()
|
||||
{
|
||||
componentsByNameByModule = new HashMap<String, Map<String, ModuleComponent>>(7);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceRegistry provides access to the service APIs
|
||||
*/
|
||||
public void setServiceRegistry(ServiceRegistry serviceRegistry)
|
||||
{
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authenticationComponent allows execution as system user.
|
||||
*/
|
||||
public void setAuthenticationComponent(AuthenticationComponent authenticationComponent)
|
||||
{
|
||||
this.authenticationComponent = authenticationComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param registryService the service used to persist component execution details.
|
||||
*/
|
||||
public void setRegistryService(RegistryService registryService)
|
||||
{
|
||||
this.registryService = registryService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param moduleService the service from which to get the available modules.
|
||||
*/
|
||||
public void setModuleService(ModuleService moduleService)
|
||||
{
|
||||
this.moduleService = moduleService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a managed module component to the registry of components. These will be controlled
|
||||
* by the {@link #startModules()} method.
|
||||
*
|
||||
* @param component a module component to be executed
|
||||
*/
|
||||
public synchronized void registerComponent(ModuleComponent component)
|
||||
{
|
||||
String moduleId = component.getModuleId();
|
||||
String name = component.getName();
|
||||
// Get the map of components for the module
|
||||
Map<String, ModuleComponent> componentsByName = componentsByNameByModule.get(moduleId);
|
||||
if (componentsByName == null)
|
||||
{
|
||||
componentsByName = new HashMap<String, ModuleComponent>(11);
|
||||
componentsByNameByModule.put(moduleId, componentsByName);
|
||||
}
|
||||
// Check if the component has already been registered
|
||||
if (componentsByName.containsKey(name))
|
||||
{
|
||||
throw AlfrescoRuntimeException.create(ERR_COMPONENT_ALREADY_REGISTERED, name, moduleId);
|
||||
}
|
||||
// Add it
|
||||
componentsByName.put(name, component);
|
||||
// Done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Registered component: " + component);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the map of components keyed by name. The map could be empty but
|
||||
* will never be <tt>null</tt>.
|
||||
*/
|
||||
private synchronized Map<String, ModuleComponent> getComponents(String moduleId)
|
||||
{
|
||||
Map<String, ModuleComponent> componentsByName = componentsByNameByModule.get(moduleId);
|
||||
if (componentsByName != null)
|
||||
{
|
||||
// Done
|
||||
return componentsByName;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Done
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public synchronized void startModules()
|
||||
{
|
||||
// Check properties
|
||||
PropertyCheck.mandatory(this, "serviceRegistry", serviceRegistry);
|
||||
PropertyCheck.mandatory(this, "authenticationComponent", authenticationComponent);
|
||||
PropertyCheck.mandatory(this, "registryService", registryService);
|
||||
PropertyCheck.mandatory(this, "moduleService", moduleService);
|
||||
/*
|
||||
* Ensure transactionality and the correct authentication
|
||||
*/
|
||||
// Get the current authentication
|
||||
Authentication authentication = authenticationComponent.getCurrentAuthentication();
|
||||
try
|
||||
{
|
||||
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);
|
||||
for (final ModuleDetails module : modules)
|
||||
{
|
||||
TransactionWork<Object> startModuleWork = new TransactionWork<Object>()
|
||||
{
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
startModule(module, executedComponents);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
TransactionUtil.executeInNonPropagatingUserTransaction(transactionService, startModuleWork);
|
||||
}
|
||||
// Done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Executed " + executedComponents.size() + " components");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Restore the original authentication
|
||||
authenticationComponent.setCurrentAuthentication(authentication);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the actual work without fussing about transactions and authentication.
|
||||
*/
|
||||
private void startModule(ModuleDetails module, Set<ModuleComponent> executedComponents)
|
||||
{
|
||||
String moduleId = module.getId();
|
||||
VersionNumber moduleVersion = module.getVersionNumber();
|
||||
// Get the module details from the registry
|
||||
RegistryKey moduleKeyInstalledVersion = new RegistryKey(
|
||||
ModuleComponentHelper.URI_MODULES_1_0,
|
||||
REGISTRY_PATH_MODULES, moduleId, REGISTRY_PROPERTY_INSTALLED_VERSION);
|
||||
RegistryKey moduleKeyCurrentVersion = new RegistryKey(
|
||||
ModuleComponentHelper.URI_MODULES_1_0,
|
||||
REGISTRY_PATH_MODULES, moduleId, REGISTRY_PROPERTY_CURRENT_VERSION);
|
||||
VersionNumber versionCurrent = (VersionNumber) registryService.getValue(moduleKeyCurrentVersion);
|
||||
String msg = null;
|
||||
if (versionCurrent == null) // There is no current version
|
||||
{
|
||||
msg = I18NUtil.getMessage(MSG_INSTALLING, moduleId, moduleVersion);
|
||||
// Record the install version
|
||||
registryService.addValue(moduleKeyInstalledVersion, moduleVersion);
|
||||
}
|
||||
else // It is an upgrade or is the same
|
||||
{
|
||||
if (versionCurrent.compareTo(moduleVersion) == 0) // The current version is the same
|
||||
{
|
||||
msg = I18NUtil.getMessage(MSG_STARTING, moduleId, moduleVersion);
|
||||
}
|
||||
else if (versionCurrent.compareTo(moduleVersion) > 0) // Downgrading not supported
|
||||
{
|
||||
throw AlfrescoRuntimeException.create(ERR_NO_DOWNGRADE, moduleId, versionCurrent, moduleVersion);
|
||||
}
|
||||
else // This is an upgrade
|
||||
{
|
||||
msg = I18NUtil.getMessage(MSG_UPGRADING, moduleId, moduleVersion, versionCurrent);
|
||||
}
|
||||
}
|
||||
loggerService.info(msg);
|
||||
// Record the current version
|
||||
registryService.addValue(moduleKeyCurrentVersion, moduleVersion);
|
||||
|
||||
Map<String, ModuleComponent> componentsByName = getComponents(moduleId);
|
||||
for (ModuleComponent component : componentsByName.values())
|
||||
{
|
||||
executeComponent(module, component, executedComponents);
|
||||
}
|
||||
|
||||
// Done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Started module: " + module);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the component, respecting dependencies.
|
||||
*/
|
||||
private void executeComponent(ModuleDetails module, ModuleComponent component, Set<ModuleComponent> executedComponents)
|
||||
{
|
||||
// Ignore if it has been executed in this run already
|
||||
if (executedComponents.contains(component))
|
||||
{
|
||||
// Already done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Skipping component already executed in this run: \n" +
|
||||
" Component: " + component);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the version applicability
|
||||
VersionNumber moduleVersion = module.getVersionNumber();
|
||||
VersionNumber minVersion = component.getAppliesFromVersionNumber();
|
||||
VersionNumber maxVersion = component.getAppliesToVersionNumber();
|
||||
if (moduleVersion.compareTo(minVersion) < 0 || moduleVersion.compareTo(maxVersion) > 0)
|
||||
{
|
||||
// It is out of the allowable range for execution so we just ignore it
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Skipping component that doesn't apply to the current version: \n" +
|
||||
" Component: " + component + "\n" +
|
||||
" Module: " + module + "\n" +
|
||||
" Version: " + moduleVersion + "\n" +
|
||||
" Applies From : " + minVersion + "\n" +
|
||||
" Applies To : " + maxVersion);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Construct the registry key to store the execution date
|
||||
String moduleId = component.getModuleId();
|
||||
String name = component.getName();
|
||||
RegistryKey executionDateKey = new RegistryKey(
|
||||
ModuleComponentHelper.URI_MODULES_1_0,
|
||||
REGISTRY_PATH_MODULES, moduleId, REGISTRY_PATH_COMPONENTS, name, REGISTRY_PROPERTY_EXECUTION_DATE);
|
||||
|
||||
// Check if the component has been executed
|
||||
Date executionDate = (Date) registryService.getValue(executionDateKey);
|
||||
if (executionDate != null && component.isExecuteOnceOnly())
|
||||
{
|
||||
// It has been executed and is scheduled for a single execution - leave it
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Skipping already-executed module component: \n" +
|
||||
" Component: " + component + "\n" +
|
||||
" Execution Time: " + executionDate);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// It may have been executed, but not in this run and it is allowed to be repeated
|
||||
// Check for dependencies
|
||||
List<ModuleComponent> dependencies = component.getDependsOn();
|
||||
for (ModuleComponent dependency : dependencies)
|
||||
{
|
||||
executeComponent(module, dependency, executedComponents);
|
||||
}
|
||||
// Execute the component itself
|
||||
component.execute();
|
||||
// Keep track of it in the registry and in this run
|
||||
executedComponents.add(component);
|
||||
registryService.addValue(executionDateKey, new Date());
|
||||
// Done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Executed module component: \n" +
|
||||
" Component: " + component);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user