1 31 32 package org.opencms.module; 33 34 import org.opencms.configuration.CmsConfigurationException; 35 import org.opencms.configuration.CmsConfigurationManager; 36 import org.opencms.configuration.CmsModuleConfiguration; 37 import org.opencms.db.CmsExportPoint; 38 import org.opencms.file.CmsObject; 39 import org.opencms.file.CmsProject; 40 import org.opencms.file.CmsResource; 41 import org.opencms.importexport.CmsImportExportManager; 42 import org.opencms.main.CmsException; 43 import org.opencms.main.CmsIllegalArgumentException; 44 import org.opencms.main.CmsIllegalStateException; 45 import org.opencms.main.CmsLog; 46 import org.opencms.main.CmsRuntimeException; 47 import org.opencms.main.OpenCms; 48 import org.opencms.report.I_CmsReport; 49 import org.opencms.security.CmsRole; 50 import org.opencms.security.CmsRoleViolationException; 51 import org.opencms.security.CmsSecurityException; 52 53 import java.io.File ; 54 import java.util.ArrayList ; 55 import java.util.Collections ; 56 import java.util.HashMap ; 57 import java.util.HashSet ; 58 import java.util.Hashtable ; 59 import java.util.Iterator ; 60 import java.util.List ; 61 import java.util.Map ; 62 import java.util.Set ; 63 64 import org.apache.commons.logging.Log; 65 66 76 public class CmsModuleManager { 77 78 79 public static final int DEPENDENCY_MODE_DELETE = 0; 80 81 82 public static final int DEPENDENCY_MODE_IMPORT = 1; 83 84 85 private static final Log LOG = CmsLog.getLog(CmsModuleManager.class); 86 87 88 private Set m_moduleExportPoints; 89 90 91 private Map m_modules; 92 93 98 public CmsModuleManager(List configuredModules) { 99 100 if (CmsLog.INIT.isInfoEnabled()) { 101 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_MOD_MANAGER_CREATED_0)); 102 } 103 104 m_modules = new Hashtable (); 105 for (int i = 0; i < configuredModules.size(); i++) { 106 CmsModule module = (CmsModule)configuredModules.get(i); 107 m_modules.put(module.getName(), module); 108 if (CmsLog.INIT.isInfoEnabled()) { 109 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_MOD_CONFIGURED_1, module.getName())); 110 } 111 } 112 113 if (CmsLog.INIT.isInfoEnabled()) { 114 CmsLog.INIT.info(Messages.get().getBundle().key( 115 Messages.INIT_NUM_MODS_CONFIGURED_1, 116 new Integer (m_modules.size()))); 117 } 118 m_moduleExportPoints = Collections.EMPTY_SET; 119 } 120 121 140 public static Map buildDepsForAllModules(String rfsAbsPath, boolean mode) throws CmsConfigurationException { 141 142 Map ret = new HashMap (); 143 List modules; 144 if (rfsAbsPath == null) { 145 modules = OpenCms.getModuleManager().getAllInstalledModules(); 146 } else { 147 modules = new ArrayList (getAllModulesFromPath(rfsAbsPath).keySet()); 148 } 149 Iterator itMods = modules.iterator(); 150 while (itMods.hasNext()) { 151 CmsModule module = (CmsModule)itMods.next(); 152 153 Iterator itDeps = module.getDependencies().iterator(); 157 while (itDeps.hasNext()) { 158 CmsModuleDependency dependency = (CmsModuleDependency)itDeps.next(); 159 String moduleDependencyName = dependency.getName(); 161 162 if (mode) { 163 List moduleDependencies = (List )ret.get(moduleDependencyName); 165 if (moduleDependencies == null) { 166 moduleDependencies = new ArrayList (); 168 ret.put(moduleDependencyName, moduleDependencies); 169 } 170 moduleDependencies.add(module.getName()); 172 } else { 173 List moduleDependencies = (List )ret.get(module.getName()); 174 if (moduleDependencies == null) { 175 moduleDependencies = new ArrayList (); 176 ret.put(module.getName(), moduleDependencies); 177 } 178 moduleDependencies.add(dependency.getName()); 179 } 180 } 181 } 182 itMods = modules.iterator(); 183 while (itMods.hasNext()) { 184 CmsModule module = (CmsModule)itMods.next(); 185 if (ret.get(module.getName()) == null) { 186 ret.put(module.getName(), new ArrayList ()); 187 } 188 } 189 return ret; 190 } 191 192 212 public static Map buildDepsForModulelist(List moduleNames, String rfsAbsPath, boolean mode) 213 throws CmsConfigurationException { 214 215 Map ret = buildDepsForAllModules(rfsAbsPath, mode); 216 Iterator itMods; 217 if (rfsAbsPath == null) { 218 itMods = OpenCms.getModuleManager().getAllInstalledModules().iterator(); 219 } else { 220 itMods = getAllModulesFromPath(rfsAbsPath).keySet().iterator(); 221 } 222 while (itMods.hasNext()) { 223 CmsModule module = (CmsModule)itMods.next(); 224 if (!moduleNames.contains(module.getName())) { 225 Iterator itDeps = ret.values().iterator(); 226 while (itDeps.hasNext()) { 227 List dependencies = (List )itDeps.next(); 228 dependencies.remove(module.getName()); 229 } 230 ret.remove(module.getName()); 231 } 232 } 233 return ret; 234 } 235 236 245 public static Map getAllModulesFromPath(String rfsAbsPath) throws CmsConfigurationException { 246 247 Map modules = new HashMap (); 248 if (rfsAbsPath == null) { 249 return modules; 250 } 251 File folder = new File (rfsAbsPath); 252 if (folder.exists()) { 253 File [] folderFiles = folder.listFiles(); 255 if (folderFiles != null) { 256 for (int i = 0; i < folderFiles.length; i++) { 257 File moduleFile = folderFiles[i]; 258 if (moduleFile.isFile() && !(moduleFile.getAbsolutePath().toLowerCase().endsWith(".zip"))) { 259 continue; 261 } 262 if (moduleFile.isDirectory()) { 263 File manifest = new File (moduleFile, CmsImportExportManager.EXPORT_MANIFEST); 264 if (!manifest.exists() || !manifest.canRead()) { 265 continue; 267 } 268 } 269 modules.put( 270 CmsModuleImportExportHandler.readModuleFromImport(moduleFile.getAbsolutePath()), 271 moduleFile.getName()); 272 } 273 } 274 } 275 return modules; 276 } 277 278 293 public static List topologicalSort(List moduleNames, String rfsAbsPath) throws CmsConfigurationException { 294 295 List modules = new ArrayList (moduleNames); 296 List retList = new ArrayList (); 297 Map moduleDependencies = buildDepsForModulelist(moduleNames, rfsAbsPath, true); 298 boolean finished = false; 299 while (!finished) { 300 finished = true; 301 Iterator itMods = modules.iterator(); 302 while (itMods.hasNext()) { 303 String moduleName = (String )itMods.next(); 304 List deps = (List )moduleDependencies.get(moduleName); 305 if ((deps == null) || deps.isEmpty()) { 306 retList.add(moduleName); 307 Iterator itDeps = moduleDependencies.values().iterator(); 308 while (itDeps.hasNext()) { 309 List dependencies = (List )itDeps.next(); 310 dependencies.remove(moduleName); 311 } 312 finished = false; 313 itMods.remove(); 314 } 315 } 316 } 317 if (!modules.isEmpty()) { 318 throw new CmsIllegalStateException(Messages.get().container( 319 Messages.ERR_MODULE_DEPENDENCY_CYCLE_1, 320 modules.toString())); 321 } 322 Collections.reverse(retList); 323 return retList; 324 } 325 326 335 public synchronized void addModule(CmsObject cms, CmsModule module) 336 throws CmsSecurityException, CmsConfigurationException { 337 338 cms.checkRole(CmsRole.MODULE_MANAGER); 340 341 if (m_modules.containsKey(module.getName())) { 342 throw new CmsConfigurationException(Messages.get().container( 344 Messages.ERR_MODULE_ALREADY_CONFIGURED_1, 345 module.getName())); 346 347 } 348 349 if (LOG.isInfoEnabled()) { 350 LOG.info(Messages.get().getBundle().key(Messages.LOG_CREATE_NEW_MOD_1, module.getName())); 351 } 352 353 module.initialize(cms); 355 356 m_modules.put(module.getName(), module); 357 358 try { 359 I_CmsModuleAction moduleAction = module.getActionInstance(); 360 if (moduleAction != null) { 362 moduleAction.moduleUpdate(module); 363 } 364 } catch (Throwable t) { 365 LOG.error(Messages.get().getBundle().key(Messages.LOG_MOD_UPDATE_ERR_1, module.getName()), t); 366 } 367 368 initModuleExportPoints(); 370 371 updateModuleConfiguration(); 373 } 374 375 390 public List checkDependencies(CmsModule module, int mode) { 391 392 List result = new ArrayList (); 393 394 if (mode == DEPENDENCY_MODE_DELETE) { 395 Iterator i = m_modules.values().iterator(); 397 while (i.hasNext()) { 398 CmsModule otherModule = (CmsModule)i.next(); 399 CmsModuleDependency dependency = otherModule.checkDependency(module); 400 if (dependency != null) { 401 result.add(new CmsModuleDependency(otherModule.getName(), otherModule.getVersion())); 403 } 404 } 405 406 } else if (mode == DEPENDENCY_MODE_IMPORT) { 407 Iterator i = m_modules.values().iterator(); 409 result.addAll(module.getDependencies()); 411 while (i.hasNext() && (result.size() > 0)) { 412 CmsModule otherModule = (CmsModule)i.next(); 413 CmsModuleDependency dependency = module.checkDependency(otherModule); 414 if (dependency != null) { 415 result.remove(dependency); 417 } 418 } 419 } else { 420 throw new CmsRuntimeException(Messages.get().container( 422 Messages.ERR_CHECK_DEPENDENCY_INVALID_MODE_1, 423 new Integer (mode))); 424 } 425 426 return result; 427 } 428 429 443 public void checkModuleSelectionList(List moduleNames, String rfsAbsPath, boolean forDeletion) 444 throws CmsIllegalArgumentException, CmsConfigurationException { 445 446 Map moduleDependencies = buildDepsForAllModules(rfsAbsPath, forDeletion); 447 Iterator itMods = moduleNames.iterator(); 448 while (itMods.hasNext()) { 449 String moduleName = (String )itMods.next(); 450 List dependencies = (List )moduleDependencies.get(moduleName); 451 if (dependencies != null) { 452 List depModules = new ArrayList (dependencies); 453 depModules.removeAll(moduleNames); 454 if (!depModules.isEmpty()) { 455 throw new CmsIllegalArgumentException(Messages.get().container( 456 Messages.ERR_MODULE_SELECTION_INCONSISTENT_2, 457 moduleName, 458 depModules.toString())); 459 } 460 } 461 } 462 } 463 464 475 public synchronized void deleteModule(CmsObject cms, String moduleName, boolean replace, I_CmsReport report) 476 throws CmsRoleViolationException, CmsConfigurationException { 477 478 cms.checkRole(CmsRole.MODULE_MANAGER); 480 481 if (!m_modules.containsKey(moduleName)) { 482 throw new CmsConfigurationException(Messages.get().container( 484 Messages.ERR_MODULE_NOT_CONFIGURED_1, 485 moduleName)); 486 } 487 488 if (LOG.isInfoEnabled()) { 489 LOG.info(Messages.get().getBundle().key(Messages.LOG_DEL_MOD_1, moduleName)); 490 } 491 492 CmsModule module; 493 boolean removeResourceTypes = false; 494 495 if (!replace) { 496 module = (CmsModule)m_modules.get(moduleName); 498 if (module.getResourceTypes() != Collections.EMPTY_LIST) { 500 removeResourceTypes = true; 501 } 502 if (module.getExplorerTypes() != Collections.EMPTY_LIST) { 503 OpenCms.getWorkplaceManager().removeExplorerTypeSettings(module); 504 } 505 506 List dependencies = checkDependencies(module, DEPENDENCY_MODE_DELETE); 508 if (!dependencies.isEmpty()) { 509 StringBuffer message = new StringBuffer (); 510 Iterator it = dependencies.iterator(); 511 while (it.hasNext()) { 512 message.append(" ").append(((CmsModuleDependency)it.next()).getName()).append("\r\n"); 513 } 514 throw new CmsConfigurationException(Messages.get().container( 515 Messages.ERR_MOD_DEPENDENCIES_2, 516 moduleName, 517 message.toString())); 518 } 519 try { 520 I_CmsModuleAction moduleAction = module.getActionInstance(); 521 if (moduleAction != null) { 523 moduleAction.moduleUninstall(module); 524 } 525 } catch (Throwable t) { 526 LOG.error(Messages.get().getBundle().key(Messages.LOG_MOD_UNINSTALL_ERR_1, moduleName), t); 527 } 528 } 529 530 module = (CmsModule)m_modules.remove(moduleName); 532 533 CmsProject previousProject = cms.getRequestContext().currentProject(); 534 try { 535 536 CmsProject deleteProject = null; 537 538 try { 539 deleteProject = cms.readProject(Messages.get().getBundle(cms.getRequestContext().getLocale()).key( 541 Messages.GUI_DELETE_MODULE_PROJECT_NAME_1, 542 new Object [] {moduleName})); 543 } catch (CmsException e) { 544 deleteProject = cms.createProject( 546 Messages.get().getBundle(cms.getRequestContext().getLocale()).key( 547 Messages.GUI_DELETE_MODULE_PROJECT_NAME_1, 548 new Object [] {moduleName}), 549 Messages.get().getBundle(cms.getRequestContext().getLocale()).key( 550 Messages.GUI_DELETE_MODULE_PROJECT_DESC_1, 551 new Object [] {moduleName}), 552 OpenCms.getDefaultUsers().getGroupAdministrators(), 553 OpenCms.getDefaultUsers().getGroupAdministrators(), 554 CmsProject.PROJECT_TYPE_TEMPORARY); 555 } 556 557 cms.getRequestContext().setCurrentProject(deleteProject); 558 559 List projectFiles = module.getResources(); 561 for (int i = 0; i < projectFiles.size(); i++) { 562 try { 563 String resourceName = (String )projectFiles.get(i); 564 if (cms.existsResource(resourceName)) { 565 cms.copyResourceToProject(resourceName); 566 } 567 } catch (CmsException e) { 568 LOG.error( 570 Messages.get().getBundle().key(Messages.LOG_MOVE_RESOURCE_FAILED_1, projectFiles.get(i)), 571 e); 572 report.println(e); 573 } 574 } 575 576 report.print(Messages.get().container(Messages.RPT_DELETE_MODULE_BEGIN_0), I_CmsReport.FORMAT_HEADLINE); 577 report.println(org.opencms.report.Messages.get().container( 578 org.opencms.report.Messages.RPT_ARGUMENT_HTML_ITAG_1, 579 moduleName), I_CmsReport.FORMAT_HEADLINE); 580 581 for (int i = 0; i < module.getResources().size(); i++) { 583 String currentResource = null; 584 try { 585 currentResource = (String )module.getResources().get(i); 586 if (LOG.isDebugEnabled()) { 587 LOG.debug(Messages.get().getBundle().key(Messages.LOG_DEL_MOD_RESOURCE_1, currentResource)); 588 } 589 if (cms.existsResource(currentResource)) { 590 cms.lockResource(currentResource); 592 cms.deleteResource(currentResource, CmsResource.DELETE_PRESERVE_SIBLINGS); 594 596 report.print(Messages.get().container(Messages.RPT_DELETE_0), I_CmsReport.FORMAT_NOTE); 597 report.println(org.opencms.report.Messages.get().container( 598 org.opencms.report.Messages.RPT_ARGUMENT_1, 599 currentResource)); 600 cms.unlockResource(currentResource); 602 } 603 } catch (CmsException e) { 604 LOG.error(Messages.get().getBundle().key(Messages.LOG_DEL_MOD_EXC_1, currentResource), e); 606 report.println(e); 607 } 608 } 609 610 report.println(Messages.get().container(Messages.RPT_PUBLISH_PROJECT_BEGIN_0), I_CmsReport.FORMAT_HEADLINE); 611 612 cms.unlockProject(deleteProject.getId()); 614 cms.publishProject(report); 615 616 report.println(Messages.get().container(Messages.RPT_PUBLISH_PROJECT_END_0), I_CmsReport.FORMAT_HEADLINE); 617 report.println(Messages.get().container(Messages.RPT_DELETE_MODULE_END_0), I_CmsReport.FORMAT_HEADLINE); 618 } catch (CmsException e) { 619 throw new CmsConfigurationException(e.getMessageContainer(), e); 620 } finally { 621 cms.getRequestContext().setCurrentProject(previousProject); 622 } 623 624 initModuleExportPoints(); 626 627 updateModuleConfiguration(); 629 630 if (removeResourceTypes) { 632 OpenCms.getResourceManager().initialize(cms); 633 } 634 } 635 636 641 public List getAllInstalledModules() { 642 643 return new ArrayList (m_modules.values()); 644 } 645 646 652 public Set getExportPoints() { 653 654 return m_moduleExportPoints; 655 } 656 657 664 public CmsModule getModule(String name) { 665 666 return (CmsModule)m_modules.get(name); 667 } 668 669 674 public Set getModuleNames() { 675 676 synchronized (m_modules) { 677 return new HashSet (m_modules.keySet()); 678 } 679 } 680 681 687 public boolean hasModule(String name) { 688 689 return m_modules.containsKey(name); 690 } 691 692 700 public synchronized void initialize(CmsObject cms, CmsConfigurationManager configurationManager) 701 throws CmsRoleViolationException { 702 703 if (OpenCms.getRunLevel() > OpenCms.RUNLEVEL_1_CORE_OBJECT) { 704 cms.checkRole(CmsRole.MODULE_MANAGER); 706 } 707 708 Iterator it; 709 int count = 0; 710 it = m_modules.keySet().iterator(); 711 while (it.hasNext()) { 712 CmsModule module = (CmsModule)m_modules.get(it.next()); 714 715 if (module.getActionClass() != null) { 716 I_CmsModuleAction moduleAction = module.getActionInstance(); 718 if (module.getActionClass() != null) { 719 try { 720 moduleAction = (I_CmsModuleAction)Class.forName(module.getActionClass()).newInstance(); 721 } catch (Exception e) { 722 CmsLog.INIT.info(Messages.get().getBundle().key( 723 Messages.INIT_CREATE_INSTANCE_FAILED_1, 724 module.getName()), e); 725 } 726 } 727 if (moduleAction != null) { 728 count++; 729 module.setActionInstance(moduleAction); 730 if (CmsLog.INIT.isInfoEnabled()) { 731 CmsLog.INIT.info(Messages.get().getBundle().key( 732 Messages.INIT_INITIALIZE_MOD_CLASS_1, 733 moduleAction.getClass().getName())); 734 } 735 try { 736 CmsObject adminCmsCopy = OpenCms.initCmsObject(cms); 739 moduleAction.initialize(adminCmsCopy, configurationManager, module); 741 } catch (Throwable t) { 742 LOG.error(Messages.get().getBundle().key( 743 Messages.LOG_INSTANCE_INIT_ERR_1, 744 moduleAction.getClass().getName()), t); 745 } 746 } 747 } 748 } 749 750 initModuleExportPoints(); 752 753 if (CmsLog.INIT.isInfoEnabled()) { 754 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_NUM_CLASSES_INITIALIZED_1, new Integer (count))); 755 } 756 } 757 758 761 public synchronized void shutDown() { 762 763 int count = 0; 764 Iterator it = getModuleNames().iterator(); 765 while (it.hasNext()) { 766 String moduleName = (String )it.next(); 767 CmsModule module = (CmsModule)m_modules.get(moduleName); 769 if (module == null) { 770 continue; 771 } 772 I_CmsModuleAction moduleAction = module.getActionInstance(); 774 if (moduleAction == null) { 775 continue; 776 } 777 778 count++; 779 if (CmsLog.INIT.isInfoEnabled()) { 780 CmsLog.INIT.info(Messages.get().getBundle().key( 781 Messages.INIT_SHUTDOWN_MOD_CLASS_1, 782 moduleAction.getClass().getName())); 783 } 784 try { 785 moduleAction.shutDown(module); 787 } catch (Throwable t) { 788 LOG.error(Messages.get().getBundle().key( 789 Messages.LOG_INSTANCE_SHUTDOWN_ERR_1, 790 moduleAction.getClass().getName()), t); 791 } 792 } 793 794 if (CmsLog.INIT.isInfoEnabled()) { 795 CmsLog.INIT.info(Messages.get().getBundle().key( 796 Messages.INIT_SHUTDOWN_NUM_MOD_CLASSES_1, 797 new Integer (count))); 798 } 799 800 if (CmsLog.INIT.isInfoEnabled()) { 801 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_SHUTDOWN_1, this.getClass().getName())); 802 } 803 } 804 805 814 public synchronized void updateModule(CmsObject cms, CmsModule module) 815 throws CmsRoleViolationException, CmsConfigurationException { 816 817 cms.checkRole(CmsRole.MODULE_MANAGER); 819 820 CmsModule oldModule = (CmsModule)m_modules.get(module.getName()); 821 822 if (oldModule == null) { 823 throw new CmsConfigurationException(Messages.get().container(Messages.ERR_OLD_MOD_ERR_1, module.getName())); 825 } 826 827 if (LOG.isInfoEnabled()) { 828 LOG.info(Messages.get().getBundle().key(Messages.LOG_MOD_UPDATE_1, module.getName())); 829 } 830 831 if (oldModule.getVersion().compareTo(module.getVersion()) == 0) { 832 module.getVersion().increment(); 834 } 835 module.getVersion().setUpdated(true); 837 838 module.initialize(cms); 840 841 m_modules.put(module.getName(), module); 843 844 try { 845 I_CmsModuleAction moduleAction = oldModule.getActionInstance(); 846 if (moduleAction != null) { 848 moduleAction.moduleUpdate(module); 849 module.setActionInstance(moduleAction); 852 } 853 } catch (Throwable t) { 854 LOG.error(Messages.get().getBundle().key(Messages.LOG_INSTANCE_UPDATE_ERR_1, module.getName()), t); 855 } 856 857 initModuleExportPoints(); 859 860 updateModuleConfiguration(); 862 } 863 864 867 private synchronized void initModuleExportPoints() { 868 869 Set exportPoints = new HashSet (); 870 Iterator i = m_modules.values().iterator(); 871 while (i.hasNext()) { 872 CmsModule module = (CmsModule)i.next(); 873 List moduleExportPoints = module.getExportPoints(); 874 for (int j = 0; j < moduleExportPoints.size(); j++) { 875 CmsExportPoint point = (CmsExportPoint)moduleExportPoints.get(j); 876 if (exportPoints.contains(point)) { 877 if (LOG.isWarnEnabled()) { 878 LOG.warn(Messages.get().getBundle().key( 879 Messages.LOG_DUPLICATE_EXPORT_POINT_2, 880 point, 881 module.getName())); 882 } 883 } else { 884 exportPoints.add(point); 885 if (LOG.isDebugEnabled()) { 886 LOG.debug(Messages.get().getBundle().key( 887 Messages.LOG_ADD_EXPORT_POINT_2, 888 point, 889 module.getName())); 890 } 891 } 892 } 893 } 894 m_moduleExportPoints = Collections.unmodifiableSet(exportPoints); 895 } 896 897 900 private void updateModuleConfiguration() { 901 902 OpenCms.writeConfiguration(CmsModuleConfiguration.class); 903 } 904 } | Popular Tags |