docs: 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.getSite();
          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<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);
  
          if (preserveLibs) {
              // to preserve the module libs, remove the responsible export points, before deleting module resources
              Set<CmsExportPoint> exportPoints = new HashSet<CmsExportPoint>(m_moduleExportPoints);
              Iterator<CmsExportPoint> 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<CmsResource> 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);
          }
  
          // reinit the workplace CSS URIs
          if (!module.getParameters().isEmpty()) {
              OpenCms.getWorkplaceAppManager().initWorkplaceCssUris(this);
          }
      }