/* * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (c) Alkacon Software GmbH (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, 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.file.CmsResourceFilter; import org.opencms.file.CmsVfsResourceNotFoundException; 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.<p> * * @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 list of module export points. */ private Set<CmsExportPoint> m_moduleExportPoints; /** The map of configured modules. */ private Map<String, CmsModule> m_modules; /** * Basic constructor.<p> * * @param configuredModules the list of configured modules */ public CmsModuleManager(List<CmsModule> configuredModules) { if (CmsLog.INIT.isInfoEnabled()) { CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_MOD_MANAGER_CREATED_0)); } m_modules = new Hashtable<String, CmsModule>(); 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.<p> * * The module dependencies are get from the installed modules or * from the module manifest.xml files found in the given FRS path.<p> * * Two types of dependency lists can be generated:<br> * <ul> * <li>Forward dependency lists: a list of modules that depends on a module</li> * <li>Backward dependency lists: a list of modules that a module depends on</li> * </ul> * * @param rfsAbsPath a RFS absolute path to search for modules, or <code>null</code> to use the installed modules * @param mode if <code>true</code> 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<String, List<String>> buildDepsForAllModules(String rfsAbsPath, boolean mode) throws CmsConfigurationException { Map<String, List<String>> ret = new HashMap<String, List<String>>(); List<CmsModule> modules; if (rfsAbsPath == null) { modules = OpenCms.getModuleManager().getAllInstalledModules(); } else { modules = new ArrayList<CmsModule>(getAllModulesFromPath(rfsAbsPath).keySet()); } Iterator<CmsModule> 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<CmsModuleDependency> 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<String> moduleDependencies = ret.get(moduleDependencyName); if (moduleDependencies == null) { // build a new list if "b" has no dependent modules yet moduleDependencies = new ArrayList<String>(); ret.put(moduleDependencyName, moduleDependencies); } // add "a" as a module depending on "b" moduleDependencies.add(module.getName()); } else { List<String> moduleDependencies = ret.get(module.getName()); if (moduleDependencies == null) { moduleDependencies = new ArrayList<String>(); 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<String>()); } } return ret; } /** * Returns a map of dependencies between the given modules.<p> * * The module dependencies are get from the installed modules or * from the module manifest.xml files found in the given FRS path.<p> * * Two types of dependency lists can be generated:<br> * <ul> * <li>Forward dependency lists: a list of modules that depends on a module</li> * <li>Backward dependency lists: a list of modules that a module depends on</li> * </ul> * * @param moduleNames a list of module names * @param rfsAbsPath a RFS absolute path to search for modules, or <code>null</code> to use the installed modules * @param mode if <code>true</code> 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<String, List<String>> buildDepsForModulelist( List<String> moduleNames, String rfsAbsPath, boolean mode) throws CmsConfigurationException { Map<String, List<String>> ret = buildDepsForAllModules(rfsAbsPath, mode); Iterator<CmsModule> 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<List<String>> itDeps = ret.values().iterator(); while (itDeps.hasNext()) { List<String> 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.<p> * * @param rfsAbsPath the path to look for module distributions * * @return a map of <code>{@link CmsModule}</code> objects for keys and filename for values * * @throws CmsConfigurationException if something goes wrong */ public static Map<CmsModule, String> getAllModulesFromPath(String rfsAbsPath) throws CmsConfigurationException { Map<CmsModule, String> modules = new HashMap<CmsModule, String>(); 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.<p> * * The module dependencies are get from the installed modules or * from the module manifest.xml files found in the given FRS path.<p> * * @param moduleNames a list of module names * @param rfsAbsPath a RFS absolute path to search for modules, or <code>null</code> to use the installed modules * * @return a sorted list of module names * * @throws CmsConfigurationException if something goes wrong */ public static List<String> topologicalSort(List<String> moduleNames, String rfsAbsPath) throws CmsConfigurationException { List<String> modules = new ArrayList<String>(moduleNames); List<String> retList = new ArrayList<String>(); Map<String, List<String>> moduleDependencies = buildDepsForModulelist(moduleNames, rfsAbsPath, true); boolean finished = false; while (!finished) { finished = true; Iterator<String> itMods = modules.iterator(); while (itMods.hasNext()) { String moduleName = itMods.next(); List<String> deps = moduleDependencies.get(moduleName); if ((deps == null) || deps.isEmpty()) { retList.add(moduleName); Iterator<List<String>> itDeps = moduleDependencies.values().iterator(); while (itDeps.hasNext()) { List<String> 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.<p> * * @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.<p> * * The possible values for the <code>mode</code> parameter are:<dl> * <dt>{@link #DEPENDENCY_MODE_DELETE}</dt> * <dd>Check for module deleting, i.e. are other modules dependent on the * given module?</dd> * <dt>{@link #DEPENDENCY_MODE_IMPORT}</dt> * <dd>Check for module importing, i.e. are all dependencies required by the given * module available?</dd></dl> * * @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<CmsModuleDependency> checkDependencies(CmsModule module, int mode) { List<CmsModuleDependency> result = new ArrayList<CmsModuleDependency>(); if (mode == DEPENDENCY_MODE_DELETE) { // delete mode, check if other modules depend on this module Iterator<CmsModule> 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<CmsModule> 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.<p> * * The module dependencies are get from the installed modules or * from the module manifest.xml files found in the given FRS path.<p> * * @param moduleNames a list of module names * @param rfsAbsPath a RFS absolute path to search for modules, or <code>null</code> 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<String> moduleNames, String rfsAbsPath, boolean forDeletion) throws CmsIllegalArgumentException, CmsConfigurationException { Map<String, List<String>> moduleDependencies = buildDepsForAllModules(rfsAbsPath, forDeletion); Iterator<String> itMods = moduleNames.iterator(); while (itMods.hasNext()) { String moduleName = itMods.next(); List<String> dependencies = moduleDependencies.get(moduleName); if (dependencies != null) { List<String> depModules = new ArrayList<String>(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.<p> * * @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 { // 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); if (!replace) { // module is deleted, not replaced // perform dependency check List<CmsModuleDependency> dependencies = checkDependencies(module, DEPENDENCY_MODE_DELETE); if (!dependencies.isEmpty()) { StringBuffer message = new StringBuffer(); Iterator<CmsModuleDependency> 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<String> lockedResources = new ArrayList<String>(); CmsLockFilter filter1 = CmsLockFilter.FILTER_ALL.filterNotLockableByUser(cms.getRequestContext().getCurrentUser()); CmsLockFilter filter2 = CmsLockFilter.FILTER_INHERITED; List<String> 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); try { cms.getRequestContext().setCurrentProject(deleteProject); // copy the module resources to the project List<String> projectFiles = module.getResources(); for (int i = 0; i < projectFiles.size(); i++) { String resourceName = projectFiles.get(i); if (cms.existsResource(resourceName, CmsResourceFilter.ALL)) { try { cms.copyResourceToProject(resourceName); } 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, resourceName)); } 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 (int i = 0; i < module.getResources().size(); i++) { String currentResource = null; try { currentResource = module.getResources().get(i); if (LOG.isDebugEnabled()) { LOG.debug(Messages.get().getBundle().key(Messages.LOG_DEL_MOD_RESOURCE_1, currentResource)); } CmsResource resource = null; try { resource = cms.readResource(currentResource, CmsResourceFilter.ALL); } catch (CmsVfsResourceNotFoundException e) { // ignore } if (resource != null) { CmsLock lock = cms.getLock(currentResource); if (lock.isUnlocked()) { // lock the resource cms.lockResource(currentResource); } else if (lock.isLockableBy(cms.getRequestContext().getCurrentUser())) { // steal the resource cms.changeLock(currentResource); } if (!resource.getState().isDeleted()) { // delete the resource cms.deleteResource(currentResource, 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, currentResource)); if (!resource.getState().isNew()) { // unlock the resource (so it gets deleted with next publish) cms.unlockResource(currentResource); } } } catch (CmsException e) { // ignore the exception and delete the next resource LOG.error(Messages.get().getBundle().key(Messages.LOG_DEL_MOD_EXC_1, currentResource), 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); } } /** * Returns a list of installed modules.<p> * * @return a list of <code>{@link CmsModule}</code> objects */ public List<CmsModule> getAllInstalledModules() { return new ArrayList<CmsModule>(m_modules.values()); } /** * Returns the (immutable) list of configured module export points.<p> * * @return the (immutable) list of configured module export points * @see CmsExportPoint */ public Set<CmsExportPoint> getExportPoints() { return m_moduleExportPoints; } /** * Returns the module with the given module name, * or <code>null</code> if no module with the given name is configured.<p> * * @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.<p> * * @return the set of names of all the installed modules */ public Set<String> getModuleNames() { synchronized (m_modules) { return new HashSet<String>(m_modules.keySet()); } } /** * Checks if this module manager has a module with the given name installed.<p> * * @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.<p> * * @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<String> 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(); 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.<p> */ public synchronized void shutDown() { int count = 0; Iterator<String> 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.<p> * * @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())); } if (oldModule.getVersion().compareTo(module.getVersion()) == 0) { // module version has not changed - auto increment version number module.getVersion().increment(); } // 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.<p> */ private synchronized void initModuleExportPoints() { Set<CmsExportPoint> exportPoints = new HashSet<CmsExportPoint>(); Iterator<CmsModule> i = m_modules.values().iterator(); while (i.hasNext()) { CmsModule module = i.next(); List<CmsExportPoint> 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.<p> */ private void updateModuleConfiguration() { OpenCms.writeConfiguration(CmsModuleConfiguration.class); } }