org.opencms.module.CmsModuleManager Maven / Gradle / Ivy
Show all versions of opencms-test Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
*
* This library 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 2.1 of the License, or (at your option) any later version.
*
* This library 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.
*
* For further information about Alkacon Software GmbH & Co. KG, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.module;
import org.opencms.configuration.CmsConfigurationException;
import org.opencms.configuration.CmsConfigurationManager;
import org.opencms.configuration.CmsModuleConfiguration;
import org.opencms.db.CmsExportPoint;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsProject;
import org.opencms.file.CmsResource;
import org.opencms.i18n.CmsMessageContainer;
import org.opencms.importexport.CmsImportExportManager;
import org.opencms.lock.CmsLock;
import org.opencms.lock.CmsLockException;
import org.opencms.lock.CmsLockFilter;
import org.opencms.main.CmsException;
import org.opencms.main.CmsIllegalArgumentException;
import org.opencms.main.CmsIllegalStateException;
import org.opencms.main.CmsLog;
import org.opencms.main.CmsRuntimeException;
import org.opencms.main.OpenCms;
import org.opencms.report.I_CmsReport;
import org.opencms.security.CmsRole;
import org.opencms.security.CmsRoleViolationException;
import org.opencms.security.CmsSecurityException;
import org.opencms.util.CmsStringUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
/**
* Manages the modules of an OpenCms installation.
*
* @since 6.0.0
*/
public class CmsModuleManager {
/** Indicates dependency check for module deletion. */
public static final int DEPENDENCY_MODE_DELETE = 0;
/** Indicates dependency check for module import. */
public static final int DEPENDENCY_MODE_IMPORT = 1;
/** The log object for this class. */
private static final Log LOG = CmsLog.getLog(CmsModuleManager.class);
/** The import/export repository. */
private CmsModuleImportExportRepository m_importExportRepository = new CmsModuleImportExportRepository();
/** The list of module export points. */
private Set m_moduleExportPoints;
/** The map of configured modules. */
private Map m_modules;
/**
* Basic constructor.
*
* @param configuredModules the list of configured modules
*/
public CmsModuleManager(List configuredModules) {
if (CmsLog.INIT.isInfoEnabled()) {
CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_MOD_MANAGER_CREATED_0));
}
m_modules = new Hashtable();
for (int i = 0; i < configuredModules.size(); i++) {
CmsModule module = configuredModules.get(i);
m_modules.put(module.getName(), module);
if (CmsLog.INIT.isInfoEnabled()) {
CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_MOD_CONFIGURED_1, module.getName()));
}
}
if (CmsLog.INIT.isInfoEnabled()) {
CmsLog.INIT.info(
Messages.get().getBundle().key(Messages.INIT_NUM_MODS_CONFIGURED_1, new Integer(m_modules.size())));
}
m_moduleExportPoints = Collections.emptySet();
}
/**
* Returns a map of dependencies.
*
* The module dependencies are get from the installed modules or
* from the module manifest.xml files found in the given FRS path.
*
* Two types of dependency lists can be generated:
*
* - Forward dependency lists: a list of modules that depends on a module
* - Backward dependency lists: a list of modules that a module depends on
*
*
* @param rfsAbsPath a RFS absolute path to search for modules, or null
to use the installed modules
* @param mode if true
a list of forward dependency is build, is not a list of backward dependency
*
* @return a Map of module names as keys and a list of dependency names as values
*
* @throws CmsConfigurationException if something goes wrong
*/
public static Map> buildDepsForAllModules(String rfsAbsPath, boolean mode)
throws CmsConfigurationException {
Map> ret = new HashMap>();
List modules;
if (rfsAbsPath == null) {
modules = OpenCms.getModuleManager().getAllInstalledModules();
} else {
modules = new ArrayList(getAllModulesFromPath(rfsAbsPath).keySet());
}
Iterator itMods = modules.iterator();
while (itMods.hasNext()) {
CmsModule module = itMods.next();
// if module a depends on module b, and module c depends also on module b:
// build a map with a list containing "a" and "c" keyed by "b" to get a
// list of modules depending on module "b"...
Iterator itDeps = module.getDependencies().iterator();
while (itDeps.hasNext()) {
CmsModuleDependency dependency = itDeps.next();
// module dependency package name
String moduleDependencyName = dependency.getName();
if (mode) {
// get the list of dependent modules
List moduleDependencies = ret.get(moduleDependencyName);
if (moduleDependencies == null) {
// build a new list if "b" has no dependent modules yet
moduleDependencies = new ArrayList();
ret.put(moduleDependencyName, moduleDependencies);
}
// add "a" as a module depending on "b"
moduleDependencies.add(module.getName());
} else {
List moduleDependencies = ret.get(module.getName());
if (moduleDependencies == null) {
moduleDependencies = new ArrayList();
ret.put(module.getName(), moduleDependencies);
}
moduleDependencies.add(dependency.getName());
}
}
}
itMods = modules.iterator();
while (itMods.hasNext()) {
CmsModule module = itMods.next();
if (ret.get(module.getName()) == null) {
ret.put(module.getName(), new ArrayList());
}
}
return ret;
}
/**
* Returns a map of dependencies between the given modules.
*
* The module dependencies are get from the installed modules or
* from the module manifest.xml files found in the given FRS path.
*
* Two types of dependency lists can be generated:
*
* - Forward dependency lists: a list of modules that depends on a module
* - Backward dependency lists: a list of modules that a module depends on
*
*
* @param moduleNames a list of module names
* @param rfsAbsPath a RFS absolute path to search for modules, or null
to use the installed modules
* @param mode if true
a list of forward dependency is build, is not a list of backward dependency
*
* @return a Map of module names as keys and a list of dependency names as values
*
* @throws CmsConfigurationException if something goes wrong
*/
public static Map> buildDepsForModulelist(
List moduleNames,
String rfsAbsPath,
boolean mode) throws CmsConfigurationException {
Map> ret = buildDepsForAllModules(rfsAbsPath, mode);
Iterator itMods;
if (rfsAbsPath == null) {
itMods = OpenCms.getModuleManager().getAllInstalledModules().iterator();
} else {
itMods = getAllModulesFromPath(rfsAbsPath).keySet().iterator();
}
while (itMods.hasNext()) {
CmsModule module = itMods.next();
if (!moduleNames.contains(module.getName())) {
Iterator> itDeps = ret.values().iterator();
while (itDeps.hasNext()) {
List dependencies = itDeps.next();
dependencies.remove(module.getName());
}
ret.remove(module.getName());
}
}
return ret;
}
/**
* Returns a map of modules found in the given RFS absolute path.
*
* @param rfsAbsPath the path to look for module distributions
*
* @return a map of {@link CmsModule}
objects for keys and filename for values
*
* @throws CmsConfigurationException if something goes wrong
*/
public static Map getAllModulesFromPath(String rfsAbsPath) throws CmsConfigurationException {
Map modules = new HashMap();
if (rfsAbsPath == null) {
return modules;
}
File folder = new File(rfsAbsPath);
if (folder.exists()) {
// list all child resources in the given folder
File[] folderFiles = folder.listFiles();
if (folderFiles != null) {
for (int i = 0; i < folderFiles.length; i++) {
File moduleFile = folderFiles[i];
if (moduleFile.isFile() && !(moduleFile.getAbsolutePath().toLowerCase().endsWith(".zip"))) {
// skip non-ZIP files
continue;
}
if (moduleFile.isDirectory()) {
File manifest = new File(moduleFile, CmsImportExportManager.EXPORT_MANIFEST);
if (!manifest.exists() || !manifest.canRead()) {
// skip unused directories
continue;
}
}
modules.put(
CmsModuleImportExportHandler.readModuleFromImport(moduleFile.getAbsolutePath()),
moduleFile.getName());
}
}
}
return modules;
}
/**
* Sorts a given list of module names by dependencies,
* so that the resulting list can be imported in that given order,
* that means modules without dependencies first.
*
* The module dependencies are get from the installed modules or
* from the module manifest.xml files found in the given FRS path.
*
* @param moduleNames a list of module names
* @param rfsAbsPath a RFS absolute path to search for modules, or null
to use the installed modules
*
* @return a sorted list of module names
*
* @throws CmsConfigurationException if something goes wrong
*/
public static List topologicalSort(List moduleNames, String rfsAbsPath)
throws CmsConfigurationException {
List modules = new ArrayList(moduleNames);
List retList = new ArrayList();
Map> moduleDependencies = buildDepsForModulelist(moduleNames, rfsAbsPath, true);
boolean finished = false;
while (!finished) {
finished = true;
Iterator itMods = modules.iterator();
while (itMods.hasNext()) {
String moduleName = itMods.next();
List deps = moduleDependencies.get(moduleName);
if ((deps == null) || deps.isEmpty()) {
retList.add(moduleName);
Iterator> itDeps = moduleDependencies.values().iterator();
while (itDeps.hasNext()) {
List dependencies = itDeps.next();
dependencies.remove(moduleName);
}
finished = false;
itMods.remove();
}
}
}
if (!modules.isEmpty()) {
throw new CmsIllegalStateException(
Messages.get().container(Messages.ERR_MODULE_DEPENDENCY_CYCLE_1, modules.toString()));
}
Collections.reverse(retList);
return retList;
}
/**
* Adds a new module to the module manager.
*
* @param cms must be initialized with "Admin" permissions
* @param module the module to add
*
* @throws CmsSecurityException if the required permissions are not available (i.e. no "Admin" CmsObject has been provided)
* @throws CmsConfigurationException if a module with this name is already configured
*/
public synchronized void addModule(CmsObject cms, CmsModule module)
throws CmsSecurityException, CmsConfigurationException {
// check the role permissions
OpenCms.getRoleManager().checkRole(cms, CmsRole.DATABASE_MANAGER);
if (m_modules.containsKey(module.getName())) {
// module is currently configured, no create possible
throw new CmsConfigurationException(
Messages.get().container(Messages.ERR_MODULE_ALREADY_CONFIGURED_1, module.getName()));
}
if (LOG.isInfoEnabled()) {
LOG.info(Messages.get().getBundle().key(Messages.LOG_CREATE_NEW_MOD_1, module.getName()));
}
// initialize the module
module.initialize(cms);
m_modules.put(module.getName(), module);
try {
I_CmsModuleAction moduleAction = module.getActionInstance();
// handle module action instance if initialized
if (moduleAction != null) {
moduleAction.moduleUpdate(module);
}
} catch (Throwable t) {
LOG.error(Messages.get().getBundle().key(Messages.LOG_MOD_UPDATE_ERR_1, module.getName()), t);
}
// initialize the export points
initModuleExportPoints();
// update the configuration
updateModuleConfiguration();
}
/**
* Checks if a modules dependencies are fulfilled.
*
* The possible values for the mode
parameter are:
* - {@link #DEPENDENCY_MODE_DELETE}
* - Check for module deleting, i.e. are other modules dependent on the
* given module?
* - {@link #DEPENDENCY_MODE_IMPORT}
* - Check for module importing, i.e. are all dependencies required by the given
* module available?
*
* @param module the module to check the dependencies for
* @param mode the dependency check mode
* @return a list of dependencies that are not fulfilled, if empty all dependencies are fulfilled
*/
public List checkDependencies(CmsModule module, int mode) {
List result = new ArrayList();
if (mode == DEPENDENCY_MODE_DELETE) {
// delete mode, check if other modules depend on this module
Iterator i = m_modules.values().iterator();
while (i.hasNext()) {
CmsModule otherModule = i.next();
CmsModuleDependency dependency = otherModule.checkDependency(module);
if (dependency != null) {
// dependency found, add to list
result.add(new CmsModuleDependency(otherModule.getName(), otherModule.getVersion()));
}
}
} else if (mode == DEPENDENCY_MODE_IMPORT) {
// import mode, check if all module dependencies are fulfilled
Iterator i = m_modules.values().iterator();
// add all dependencies that must be found
result.addAll(module.getDependencies());
while (i.hasNext() && (result.size() > 0)) {
CmsModule otherModule = i.next();
CmsModuleDependency dependency = module.checkDependency(otherModule);
if (dependency != null) {
// dependency found, remove from list
result.remove(dependency);
}
}
} else {
// invalid mode selected
throw new CmsRuntimeException(
Messages.get().container(Messages.ERR_CHECK_DEPENDENCY_INVALID_MODE_1, new Integer(mode)));
}
return result;
}
/**
* Checks the module selection list for consistency, that means
* that if a module is selected, all its dependencies are also selected.
*
* The module dependencies are get from the installed modules or
* from the module manifest.xml files found in the given FRS path.
*
* @param moduleNames a list of module names
* @param rfsAbsPath a RFS absolute path to search for modules, or null
to use the installed modules
* @param forDeletion there are two modes, one for installation of modules, and one for deletion.
*
* @throws CmsIllegalArgumentException if the module list is not consistent
* @throws CmsConfigurationException if something goes wrong
*/
public void checkModuleSelectionList(List moduleNames, String rfsAbsPath, boolean forDeletion)
throws CmsIllegalArgumentException, CmsConfigurationException {
Map> moduleDependencies = buildDepsForAllModules(rfsAbsPath, forDeletion);
Iterator itMods = moduleNames.iterator();
while (itMods.hasNext()) {
String moduleName = itMods.next();
List dependencies = moduleDependencies.get(moduleName);
if (dependencies != null) {
List depModules = new ArrayList(dependencies);
depModules.removeAll(moduleNames);
if (!depModules.isEmpty()) {
throw new CmsIllegalArgumentException(
Messages.get().container(
Messages.ERR_MODULE_SELECTION_INCONSISTENT_2,
moduleName,
depModules.toString()));
}
}
}
}
/**
* Deletes a module from the configuration.
*
* @param cms must be initialized with "Admin" permissions
* @param moduleName the name of the module to delete
* @param replace indicates if the module is replaced (true) or finally deleted (false)
* @param report the report to print progress messages to
*
* @throws CmsRoleViolationException if the required module manager role permissions are not available
* @throws CmsConfigurationException if a module with this name is not available for deleting
* @throws CmsLockException if the module resources can not be locked
*/
public synchronized void deleteModule(
CmsObject cms,
String moduleName,
boolean replace,
boolean preserveLibs,
I_CmsReport report) throws CmsRoleViolationException, CmsConfigurationException, CmsLockException {
// check for module manager role permissions
OpenCms.getRoleManager().checkRole(cms, CmsRole.DATABASE_MANAGER);
if (!m_modules.containsKey(moduleName)) {
// module is not currently configured, no update possible
throw new CmsConfigurationException(
Messages.get().container(Messages.ERR_MODULE_NOT_CONFIGURED_1, moduleName));
}
if (LOG.isInfoEnabled()) {
LOG.info(Messages.get().getBundle().key(Messages.LOG_DEL_MOD_1, moduleName));
}
CmsModule module = m_modules.get(moduleName);
String importSite = module.getImportSite();
if (!CmsStringUtil.isEmptyOrWhitespaceOnly(importSite)) {
CmsObject newCms;
try {
newCms = OpenCms.initCmsObject(cms);
newCms.getRequestContext().setSiteRoot(importSite);
cms = newCms;
} catch (CmsException e) {
LOG.error(e.getLocalizedMessage(), e);
}
}
if (!replace) {
// module is deleted, not replaced
// perform dependency check
List dependencies = checkDependencies(module, DEPENDENCY_MODE_DELETE);
if (!dependencies.isEmpty()) {
StringBuffer message = new StringBuffer();
Iterator it = dependencies.iterator();
while (it.hasNext()) {
message.append(" ").append(it.next().getName()).append("\r\n");
}
throw new CmsConfigurationException(
Messages.get().container(Messages.ERR_MOD_DEPENDENCIES_2, moduleName, message.toString()));
}
try {
I_CmsModuleAction moduleAction = module.getActionInstance();
// handle module action instance if initialized
if (moduleAction != null) {
moduleAction.moduleUninstall(module);
}
} catch (Throwable t) {
LOG.error(Messages.get().getBundle().key(Messages.LOG_MOD_UNINSTALL_ERR_1, moduleName), t);
report.println(
Messages.get().container(Messages.LOG_MOD_UNINSTALL_ERR_1, moduleName),
I_CmsReport.FORMAT_WARNING);
}
}
boolean removeResourceTypes = !module.getResourceTypes().isEmpty();
if (removeResourceTypes) {
// mark the resource manager to reinitialize if necessary
OpenCms.getWorkplaceManager().removeExplorerTypeSettings(module);
}
CmsProject previousProject = cms.getRequestContext().getCurrentProject();
// try to create a new offline project for deletion
CmsProject deleteProject = null;
try {
// try to read a (leftover) module delete project
deleteProject = cms.readProject(
Messages.get().getBundle(cms.getRequestContext().getLocale()).key(
Messages.GUI_DELETE_MODULE_PROJECT_NAME_1,
new Object[] {moduleName}));
} catch (CmsException e) {
try {
// create a Project to delete the module
deleteProject = cms.createProject(
Messages.get().getBundle(cms.getRequestContext().getLocale()).key(
Messages.GUI_DELETE_MODULE_PROJECT_NAME_1,
new Object[] {moduleName}),
Messages.get().getBundle(cms.getRequestContext().getLocale()).key(
Messages.GUI_DELETE_MODULE_PROJECT_DESC_1,
new Object[] {moduleName}),
OpenCms.getDefaultUsers().getGroupAdministrators(),
OpenCms.getDefaultUsers().getGroupAdministrators(),
CmsProject.PROJECT_TYPE_TEMPORARY);
} catch (CmsException e1) {
throw new CmsConfigurationException(e1.getMessageContainer(), e1);
}
}
try {
cms.getRequestContext().setCurrentProject(deleteProject);
// check locks
List lockedResources = new ArrayList();
CmsLockFilter filter1 = CmsLockFilter.FILTER_ALL.filterNotLockableByUser(
cms.getRequestContext().getCurrentUser());
CmsLockFilter filter2 = CmsLockFilter.FILTER_INHERITED;
List moduleResources = module.getResources();
for (int iLock = 0; iLock < moduleResources.size(); iLock++) {
String resourceName = moduleResources.get(iLock);
try {
lockedResources.addAll(cms.getLockedResources(resourceName, filter1));
lockedResources.addAll(cms.getLockedResources(resourceName, filter2));
} catch (CmsException e) {
// may happen if the resource has already been deleted
if (LOG.isDebugEnabled()) {
LOG.debug(e.getMessageContainer(), e);
}
report.println(e.getMessageContainer(), I_CmsReport.FORMAT_WARNING);
}
}
if (!lockedResources.isEmpty()) {
CmsMessageContainer msg = Messages.get().container(
Messages.ERR_DELETE_MODULE_CHECK_LOCKS_2,
moduleName,
CmsStringUtil.collectionAsString(lockedResources, ","));
report.addError(msg.key(cms.getRequestContext().getLocale()));
report.println(msg);
cms.getRequestContext().setCurrentProject(previousProject);
try {
cms.deleteProject(deleteProject.getUuid());
} catch (CmsException e1) {
throw new CmsConfigurationException(e1.getMessageContainer(), e1);
}
throw new CmsLockException(msg);
}
} finally {
cms.getRequestContext().setCurrentProject(previousProject);
}
// now remove the module
module = m_modules.remove(moduleName);
if (preserveLibs) {
// to preserve the module libs, remove the responsible export points, before deleting module resources
Set exportPoints = new HashSet(m_moduleExportPoints);
Iterator it = exportPoints.iterator();
while (it.hasNext()) {
CmsExportPoint point = it.next();
if ((point.getUri().endsWith(module.getName() + "/lib/")
|| point.getUri().endsWith(module.getName() + "/lib"))
&& point.getConfiguredDestination().equals("WEB-INF/lib/")) {
it.remove();
}
}
m_moduleExportPoints = Collections.unmodifiableSet(exportPoints);
}
try {
cms.getRequestContext().setCurrentProject(deleteProject);
// copy the module resources to the project
List moduleResources = CmsModule.calculateModuleResources(cms, module);
for (CmsResource resource : moduleResources) {
try {
cms.copyResourceToProject(resource);
} catch (CmsException e) {
// may happen if the resource has already been deleted
if (LOG.isDebugEnabled()) {
LOG.debug(
Messages.get().getBundle().key(
Messages.LOG_MOVE_RESOURCE_FAILED_1,
cms.getSitePath(resource)));
}
report.println(e.getMessageContainer(), I_CmsReport.FORMAT_WARNING);
}
}
report.print(Messages.get().container(Messages.RPT_DELETE_MODULE_BEGIN_0), I_CmsReport.FORMAT_HEADLINE);
report.println(
org.opencms.report.Messages.get().container(
org.opencms.report.Messages.RPT_ARGUMENT_HTML_ITAG_1,
moduleName),
I_CmsReport.FORMAT_HEADLINE);
// move through all module resources and delete them
for (CmsResource resource : moduleResources) {
String sitePath = cms.getSitePath(resource);
try {
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.get().getBundle().key(Messages.LOG_DEL_MOD_RESOURCE_1, sitePath));
}
CmsLock lock = cms.getLock(resource);
if (lock.isUnlocked()) {
// lock the resource
cms.lockResource(resource);
} else if (lock.isLockableBy(cms.getRequestContext().getCurrentUser())) {
// steal the resource
cms.changeLock(resource);
}
if (!resource.getState().isDeleted()) {
// delete the resource
cms.deleteResource(sitePath, CmsResource.DELETE_PRESERVE_SIBLINGS);
}
// update the report
report.print(Messages.get().container(Messages.RPT_DELETE_0), I_CmsReport.FORMAT_NOTE);
report.println(
org.opencms.report.Messages.get().container(
org.opencms.report.Messages.RPT_ARGUMENT_1,
sitePath));
if (!resource.getState().isNew()) {
// unlock the resource (so it gets deleted with next publish)
cms.unlockResource(resource);
}
} catch (CmsException e) {
// ignore the exception and delete the next resource
LOG.error(Messages.get().getBundle().key(Messages.LOG_DEL_MOD_EXC_1, sitePath), e);
report.println(e.getMessageContainer(), I_CmsReport.FORMAT_WARNING);
}
}
report.println(Messages.get().container(Messages.RPT_PUBLISH_PROJECT_BEGIN_0), I_CmsReport.FORMAT_HEADLINE);
// now unlock and publish the project
cms.unlockProject(deleteProject.getUuid());
OpenCms.getPublishManager().publishProject(cms, report);
OpenCms.getPublishManager().waitWhileRunning();
report.println(Messages.get().container(Messages.RPT_PUBLISH_PROJECT_END_0), I_CmsReport.FORMAT_HEADLINE);
report.println(Messages.get().container(Messages.RPT_DELETE_MODULE_END_0), I_CmsReport.FORMAT_HEADLINE);
} catch (CmsException e) {
throw new CmsConfigurationException(e.getMessageContainer(), e);
} finally {
cms.getRequestContext().setCurrentProject(previousProject);
}
// initialize the export points (removes export points from deleted module)
initModuleExportPoints();
// update the configuration
updateModuleConfiguration();
// reinit the manager is necessary
if (removeResourceTypes) {
OpenCms.getResourceManager().initialize(cms);
}
}
/**
* Deletes a module from the configuration.
*
* @param cms must be initialized with "Admin" permissions
* @param moduleName the name of the module to delete
* @param replace indicates if the module is replaced (true) or finally deleted (false)
* @param report the report to print progress messages to
*
* @throws CmsRoleViolationException if the required module manager role permissions are not available
* @throws CmsConfigurationException if a module with this name is not available for deleting
* @throws CmsLockException if the module resources can not be locked
*/
public synchronized void deleteModule(CmsObject cms, String moduleName, boolean replace, I_CmsReport report)
throws CmsRoleViolationException, CmsConfigurationException, CmsLockException {
deleteModule(cms, moduleName, replace, false, report);
}
/**
* Returns a list of installed modules.
*
* @return a list of {@link CmsModule}
objects
*/
public List getAllInstalledModules() {
return new ArrayList(m_modules.values());
}
/**
* Returns the (immutable) list of configured module export points.
*
* @return the (immutable) list of configured module export points
* @see CmsExportPoint
*/
public Set getExportPoints() {
return m_moduleExportPoints;
}
/**
* Returns the importExportRepository.
*
* @return the importExportRepository
*/
public CmsModuleImportExportRepository getImportExportRepository() {
return m_importExportRepository;
}
/**
* Returns the module with the given module name,
* or null
if no module with the given name is configured.
*
* @param name the name of the module to return
* @return the module with the given module name
*/
public CmsModule getModule(String name) {
return m_modules.get(name);
}
/**
* Returns the set of names of all the installed modules.
*
* @return the set of names of all the installed modules
*/
public Set getModuleNames() {
synchronized (m_modules) {
return new HashSet(m_modules.keySet());
}
}
/**
* Checks if this module manager has a module with the given name installed.
*
* @param name the name of the module to check
* @return true if this module manager has a module with the given name installed
*/
public boolean hasModule(String name) {
return m_modules.containsKey(name);
}
/**
* Initializes all module instance classes managed in this module manager.
*
* @param cms an initialized CmsObject with "manage modules" role permissions
* @param configurationManager the initialized OpenCms configuration manager
*
* @throws CmsRoleViolationException if the provided OpenCms context does not have "manage modules" role permissions
*/
public synchronized void initialize(CmsObject cms, CmsConfigurationManager configurationManager)
throws CmsRoleViolationException {
if (OpenCms.getRunLevel() > OpenCms.RUNLEVEL_1_CORE_OBJECT) {
// certain test cases won't have an OpenCms context
OpenCms.getRoleManager().checkRole(cms, CmsRole.DATABASE_MANAGER);
}
Iterator it;
int count = 0;
it = m_modules.keySet().iterator();
while (it.hasNext()) {
// get the module description
CmsModule module = m_modules.get(it.next());
if (module.getActionClass() != null) {
// create module instance class
I_CmsModuleAction moduleAction = module.getActionInstance();
if (module.getActionClass() != null) {
try {
moduleAction = (I_CmsModuleAction)Class.forName(module.getActionClass()).newInstance();
} catch (Exception e) {
CmsLog.INIT.info(
Messages.get().getBundle().key(Messages.INIT_CREATE_INSTANCE_FAILED_1, module.getName()),
e);
}
}
if (moduleAction != null) {
count++;
module.setActionInstance(moduleAction);
if (CmsLog.INIT.isInfoEnabled()) {
CmsLog.INIT.info(
Messages.get().getBundle().key(
Messages.INIT_INITIALIZE_MOD_CLASS_1,
moduleAction.getClass().getName()));
}
try {
// create a copy of the adminCms so that each module instance does have
// it's own context, a shared context might introduce side - effects
CmsObject adminCmsCopy = OpenCms.initCmsObject(cms);
// initialize the module
moduleAction.initialize(adminCmsCopy, configurationManager, module);
} catch (Throwable t) {
LOG.error(
Messages.get().getBundle().key(
Messages.LOG_INSTANCE_INIT_ERR_1,
moduleAction.getClass().getName()),
t);
}
}
}
}
// initialize the export points
initModuleExportPoints();
m_importExportRepository.initialize(cms);
if (CmsLog.INIT.isInfoEnabled()) {
CmsLog.INIT.info(
Messages.get().getBundle().key(Messages.INIT_NUM_CLASSES_INITIALIZED_1, new Integer(count)));
}
}
/**
* Shuts down all module instance classes managed in this module manager.
*/
public synchronized void shutDown() {
int count = 0;
Iterator it = getModuleNames().iterator();
while (it.hasNext()) {
String moduleName = it.next();
// get the module
CmsModule module = m_modules.get(moduleName);
if (module == null) {
continue;
}
// get the module action instance
I_CmsModuleAction moduleAction = module.getActionInstance();
if (moduleAction == null) {
continue;
}
count++;
if (CmsLog.INIT.isInfoEnabled()) {
CmsLog.INIT.info(
Messages.get().getBundle().key(
Messages.INIT_SHUTDOWN_MOD_CLASS_1,
moduleAction.getClass().getName()));
}
try {
// shut down the module
moduleAction.shutDown(module);
} catch (Throwable t) {
LOG.error(
Messages.get().getBundle().key(
Messages.LOG_INSTANCE_SHUTDOWN_ERR_1,
moduleAction.getClass().getName()),
t);
}
}
if (CmsLog.INIT.isInfoEnabled()) {
CmsLog.INIT.info(
Messages.get().getBundle().key(Messages.INIT_SHUTDOWN_NUM_MOD_CLASSES_1, new Integer(count)));
}
if (CmsLog.INIT.isInfoEnabled()) {
CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_SHUTDOWN_1, this.getClass().getName()));
}
}
/**
* Updates a already configured module with new values.
*
* @param cms must be initialized with "Admin" permissions
* @param module the module to update
*
* @throws CmsRoleViolationException if the required module manager role permissions are not available
* @throws CmsConfigurationException if a module with this name is not available for updating
*/
public synchronized void updateModule(CmsObject cms, CmsModule module)
throws CmsRoleViolationException, CmsConfigurationException {
// check for module manager role permissions
OpenCms.getRoleManager().checkRole(cms, CmsRole.DATABASE_MANAGER);
CmsModule oldModule = m_modules.get(module.getName());
if (oldModule == null) {
// module is not currently configured, no update possible
throw new CmsConfigurationException(Messages.get().container(Messages.ERR_OLD_MOD_ERR_1, module.getName()));
}
if (LOG.isInfoEnabled()) {
LOG.info(Messages.get().getBundle().key(Messages.LOG_MOD_UPDATE_1, module.getName()));
}
// indicate that the version number was recently updated
module.getVersion().setUpdated(true);
// initialize (freeze) the module
module.initialize(cms);
// replace old version of module with new version
m_modules.put(module.getName(), module);
try {
I_CmsModuleAction moduleAction = oldModule.getActionInstance();
// handle module action instance if initialized
if (moduleAction != null) {
moduleAction.moduleUpdate(module);
// set the old action instance
// the new action instance will be used after a system restart
module.setActionInstance(moduleAction);
}
} catch (Throwable t) {
LOG.error(Messages.get().getBundle().key(Messages.LOG_INSTANCE_UPDATE_ERR_1, module.getName()), t);
}
// initialize the export points
initModuleExportPoints();
// update the configuration
updateModuleConfiguration();
}
/**
* Initializes the list of export points from all configured modules.
*/
private synchronized void initModuleExportPoints() {
Set exportPoints = new HashSet();
Iterator i = m_modules.values().iterator();
while (i.hasNext()) {
CmsModule module = i.next();
List moduleExportPoints = module.getExportPoints();
for (int j = 0; j < moduleExportPoints.size(); j++) {
CmsExportPoint point = moduleExportPoints.get(j);
if (exportPoints.contains(point)) {
if (LOG.isWarnEnabled()) {
LOG.warn(
Messages.get().getBundle().key(
Messages.LOG_DUPLICATE_EXPORT_POINT_2,
point,
module.getName()));
}
} else {
exportPoints.add(point);
if (LOG.isDebugEnabled()) {
LOG.debug(
Messages.get().getBundle().key(Messages.LOG_ADD_EXPORT_POINT_2, point, module.getName()));
}
}
}
}
m_moduleExportPoints = Collections.unmodifiableSet(exportPoints);
}
/**
* Updates the module configuration.
*/
private void updateModuleConfiguration() {
OpenCms.writeConfiguration(CmsModuleConfiguration.class);
}
}