001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.module; 029 030import org.opencms.db.CmsExportPoint; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsResource; 033import org.opencms.file.CmsResourceFilter; 034import org.opencms.file.types.I_CmsResourceType; 035import org.opencms.main.CmsException; 036import org.opencms.main.CmsIllegalArgumentException; 037import org.opencms.main.CmsLog; 038import org.opencms.main.OpenCms; 039import org.opencms.security.CmsRole; 040import org.opencms.security.CmsRoleViolationException; 041import org.opencms.util.CmsFileUtil; 042import org.opencms.util.CmsStringUtil; 043import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 044 045import java.util.ArrayList; 046import java.util.Collections; 047import java.util.List; 048import java.util.Map; 049import java.util.SortedMap; 050import java.util.StringTokenizer; 051import java.util.TreeMap; 052 053import org.apache.commons.logging.Log; 054 055/** 056 * Describes an OpenCms module.<p> 057 * 058 * OpenCms modules provide a standard mechanism to extend the OpenCms functionality. 059 * Modules can contain VFS data, Java classes and a number of configuration options.<p> 060 * 061 * @since 6.0.0 062 * 063 * @see org.opencms.module.I_CmsModuleAction 064 * @see org.opencms.module.A_CmsModuleAction 065 */ 066public class CmsModule implements Comparable<CmsModule> { 067 068 /** The available module export modes. */ 069 public enum ExportMode { 070 /** Default export mode. */ 071 DEFAULT, /** Reduced export, that omits last modification information (dates and users). */ 072 REDUCED; 073 074 /** 075 * @see java.lang.Enum#toString() 076 */ 077 @Override 078 public String toString() { 079 080 return super.toString().toLowerCase(); 081 } 082 } 083 084 /** The default date for module created / installed if not provided. */ 085 public static final long DEFAULT_DATE = 0L; 086 087 /** The log object for this class. */ 088 private static final Log LOG = CmsLog.getLog(CmsModule.class); 089 090 /** 091 * The module property key name to specifiy additional resources which are 092 * part of a module outside of {system/modules}. 093 */ 094 private static final String MODULE_PROPERTY_ADDITIONAL_RESOURCES = "additionalresources"; 095 096 /** Character to separate additional resources specified in the module properties. */ 097 private static final String MODULE_PROPERTY_ADDITIONAL_RESOURCES_SEPARATOR = ";"; 098 099 /** The module action class name. */ 100 private String m_actionClass; 101 102 /** Initialized module action instance. */ 103 private I_CmsModuleAction m_actionInstance; 104 105 /** The email of the author of this module. */ 106 private String m_authorEmail; 107 108 /** The name of the author of this module. */ 109 private String m_authorName; 110 111 /** Flag to create the classes folders when creating the module. */ 112 private boolean m_createClassesFolder; 113 114 /** Flag to create the elements folder when creating the module. */ 115 private boolean m_createElementsFolder; 116 117 /** Flag to create the formatters folder when creating the module. */ 118 private boolean m_createFormattersFolder; 119 120 /** Flag to create the lib folder when creating the module. */ 121 private boolean m_createLibFolder; 122 123 /** Flag to create the module folder when creating the module. */ 124 private boolean m_createModuleFolder; 125 126 /** Flag to create the resources folder when creating the module. */ 127 private boolean m_createResourcesFolder; 128 129 /** Flag to create the schemas folder when creating the module. */ 130 private boolean m_createSchemasFolder; 131 132 /** Flag to create the template folder when creating the module. */ 133 private boolean m_createTemplateFolder; 134 135 /** The date this module was created by the author. */ 136 private long m_dateCreated; 137 138 /** The date this module was installed. */ 139 private long m_dateInstalled; 140 141 /** List of dependencies of this module. */ 142 private List<CmsModuleDependency> m_dependencies; 143 144 /** The description of this module. */ 145 private String m_description; 146 147 /** The explorer type settings. */ 148 private List<CmsExplorerTypeSettings> m_explorerTypeSettings; 149 150 /** List of export points added by this module. */ 151 private List<CmsExportPoint> m_exportPoints; 152 153 /** Indicates if this modules configuration has already been frozen. */ 154 private boolean m_frozen; 155 156 /** The group of the module. */ 157 private String m_group; 158 159 /** The script to execute when the module is imported. */ 160 private String m_importScript; 161 162 /** The import site. */ 163 private String m_importSite; 164 165 /** The name of this module, must be a valid Java package name. */ 166 private String m_name; 167 168 /** The "nice" display name of this module. */ 169 private String m_niceName; 170 171 /** A timestamp from the time this object was created. */ 172 private long m_objectCreateTime = System.currentTimeMillis(); 173 174 /** The additional configuration parameters of this module. */ 175 private SortedMap<String, String> m_parameters; 176 177 /** The export mode to use for the module. */ 178 private ExportMode m_exportMode; 179 180 /** List of VFS resources that belong to this module. */ 181 private List<String> m_resources; 182 183 /** List of VFS resources that do not belong to this module. 184 * In particular used for files / folders in folders that belong to the module. 185 */ 186 private List<String> m_excluderesources; 187 188 /** The list of additional resource types. */ 189 private List<I_CmsResourceType> m_resourceTypes; 190 191 /** The name of the user who installed this module. */ 192 private String m_userInstalled; 193 194 /** The version of this module. */ 195 private CmsModuleVersion m_version; 196 197 /** 198 * Creates a new, empty CmsModule object.<p> 199 */ 200 public CmsModule() { 201 202 m_version = new CmsModuleVersion(CmsModuleVersion.DEFAULT_VERSION); 203 m_resources = Collections.emptyList(); 204 m_excluderesources = Collections.emptyList(); 205 m_exportPoints = Collections.emptyList(); 206 m_dependencies = Collections.emptyList(); 207 m_exportMode = ExportMode.DEFAULT; 208 } 209 210 /** 211 * Creates a new module description with the specified values.<p> 212 * 213 * @param name the name of this module, must be a valid Java package name 214 * @param niceName the "nice" display name of this module 215 * @param group the group of this module 216 * @param actionClass the (optional) module class name 217 * @param importScript the script to execute when the module is imported 218 * @param importSite the site root into which this module should be imported 219 * @param exportMode the export mode that should be used for the module 220 * @param description the description of this module 221 * @param version the version of this module 222 * @param authorName the name of the author of this module 223 * @param authorEmail the email of the author of this module 224 * @param dateCreated the date this module was created by the author 225 * @param userInstalled the name of the user who uploaded this module 226 * @param dateInstalled the date this module was uploaded 227 * @param dependencies a list of dependencies of this module 228 * @param exportPoints a list of export point added by this module 229 * @param resources a list of VFS resources that belong to this module 230 * @param excluderesources a list of VFS resources that are exclude from the module's resources 231 * @param parameters the parameters for this module 232 */ 233 public CmsModule( 234 String name, 235 String niceName, 236 String group, 237 String actionClass, 238 String importScript, 239 String importSite, 240 ExportMode exportMode, 241 String description, 242 CmsModuleVersion version, 243 String authorName, 244 String authorEmail, 245 long dateCreated, 246 String userInstalled, 247 long dateInstalled, 248 List<CmsModuleDependency> dependencies, 249 List<CmsExportPoint> exportPoints, 250 List<String> resources, 251 List<String> excluderesources, 252 Map<String, String> parameters) { 253 254 super(); 255 m_name = name; 256 setNiceName(niceName); 257 setActionClass(actionClass); 258 setGroup(group); 259 260 m_exportMode = null == exportMode ? ExportMode.DEFAULT : exportMode; 261 262 if (CmsStringUtil.isEmpty(description)) { 263 m_description = ""; 264 } else { 265 m_description = description; 266 } 267 m_version = version; 268 if (CmsStringUtil.isEmpty(authorName)) { 269 m_authorName = ""; 270 } else { 271 m_authorName = authorName; 272 } 273 if (CmsStringUtil.isEmpty(authorEmail)) { 274 m_authorEmail = ""; 275 } else { 276 m_authorEmail = authorEmail; 277 } 278 // remove milisecounds 279 m_dateCreated = (dateCreated / 1000L) * 1000L; 280 if (CmsStringUtil.isEmpty(userInstalled)) { 281 m_userInstalled = ""; 282 } else { 283 m_userInstalled = userInstalled; 284 } 285 m_dateInstalled = (dateInstalled / 1000L) * 1000L; 286 if (dependencies == null) { 287 m_dependencies = Collections.emptyList(); 288 } else { 289 m_dependencies = Collections.unmodifiableList(dependencies); 290 } 291 if (exportPoints == null) { 292 m_exportPoints = Collections.emptyList(); 293 } else { 294 m_exportPoints = Collections.unmodifiableList(exportPoints); 295 } 296 if (resources == null) { 297 m_resources = Collections.emptyList(); 298 } else { 299 m_resources = Collections.unmodifiableList(resources); 300 } 301 if (excluderesources == null) { 302 m_excluderesources = Collections.emptyList(); 303 } else { 304 m_excluderesources = Collections.unmodifiableList(excluderesources); 305 } 306 if (parameters == null) { 307 m_parameters = new TreeMap<String, String>(); 308 } else { 309 m_parameters = new TreeMap<String, String>(parameters); 310 } 311 m_importSite = importSite; 312 313 m_importScript = importScript; 314 315 initOldAdditionalResources(); 316 317 if (LOG.isDebugEnabled()) { 318 LOG.debug(Messages.get().getBundle().key(Messages.LOG_MODULE_INSTANCE_CREATED_1, m_name)); 319 } 320 m_resourceTypes = Collections.emptyList(); 321 m_explorerTypeSettings = Collections.emptyList(); 322 } 323 324 /** Determines the resources that are: 325 * <ul> 326 * <li>accessible with the provided {@link CmsObject},</li> 327 * <li>part of the <code>moduleResources</code> (or in a folder of these resources) and</li> 328 * <li><em>not</em> contained in <code>excludedResources</code> (or a folder of these resources).</li> 329 * </ul> 330 * and adds the to <code>result</code> 331 * 332 * @param result the resource list, that gets extended by the calculated resources. 333 * @param cms the {@link CmsObject} used to read resources. 334 * @param moduleResources the resources to include. 335 * @param excludeResources the site paths of the resources to exclude. 336 * @throws CmsException thrown if reading resources fails. 337 */ 338 public static void addCalculatedModuleResources( 339 List<CmsResource> result, 340 final CmsObject cms, 341 final List<CmsResource> moduleResources, 342 final List<String> excludeResources) throws CmsException { 343 344 for (CmsResource resource : moduleResources) { 345 346 String sitePath = cms.getSitePath(resource); 347 348 List<String> excludedSubResources = getExcludedForResource(sitePath, excludeResources); 349 350 // check if resources have to be excluded 351 if (excludedSubResources.isEmpty()) { 352 // no resource has to be excluded - add the whole resource 353 // (that is, also all resources in the folder, if the resource is a folder) 354 result.add(resource); 355 } else { 356 // cannot add the complete resource (i.e., including the whole sub-tree) 357 if (sitePath.equals(excludedSubResources.get(0))) { 358 // the resource itself is excluded -> do not add it and check the next resource 359 continue; 360 } 361 // try to include sub-resources. 362 List<CmsResource> subResources = cms.readResources(sitePath, CmsResourceFilter.ALL, false); 363 addCalculatedModuleResources(result, cms, subResources, excludedSubResources); 364 } 365 } 366 367 } 368 369 /** Calculates the resources belonging to the module, taking excluded resources and readability of resources into account, 370 * and returns site paths of the module resources.<p> 371 * For more details of the returned resource, see {@link #calculateModuleResources(CmsObject, CmsModule)}. 372 * 373 * @param cms the {@link CmsObject} used to read the resources. 374 * @param module the module, for which the resources should be calculated 375 * @return the calculated module resources 376 * @throws CmsException thrown if reading resources fails. 377 */ 378 public static List<String> calculateModuleResourceNames(final CmsObject cms, final CmsModule module) 379 throws CmsException { 380 381 // adjust the site root, if necessary 382 CmsObject cmsClone = adjustSiteRootIfNecessary(cms, module); 383 384 // calculate the module resources 385 List<CmsResource> moduleResources = calculateModuleResources(cmsClone, module); 386 387 // get the site paths 388 List<String> moduleResouceNames = new ArrayList<String>(moduleResources.size()); 389 for (CmsResource resource : moduleResources) { 390 moduleResouceNames.add(cmsClone.getSitePath(resource)); 391 } 392 return moduleResouceNames; 393 } 394 395 /** Calculates and returns the resources belonging to the module, taking excluded resources and readability of resources into account. 396 * The list of returned resources contains: 397 * <ul> 398 * <li>Only resources that are readable (present at the system and accessible with the provided {@link CmsObject}</li> 399 * <li>Only the resource for a folder, if <em>all</em> resources in the folder belong to the module.</li> 400 * <li>Only resources that are specified as module resources and <em>not</em> excluded by the module's exclude resources.</li> 401 * </ul> 402 * 403 * @param cms the {@link CmsObject} used to read the resources. 404 * @param module the module, for which the resources should be calculated 405 * @return the calculated module resources 406 * @throws CmsException thrown if reading resources fails. 407 */ 408 public static List<CmsResource> calculateModuleResources(final CmsObject cms, final CmsModule module) 409 throws CmsException { 410 411 CmsObject cmsClone = adjustSiteRootIfNecessary(cms, module); 412 List<CmsResource> result = null; 413 List<String> excluded = CmsFileUtil.removeRedundancies(module.getExcludeResources()); 414 excluded = removeNonAccessible(cmsClone, excluded); 415 List<String> resourceSitePaths = CmsFileUtil.removeRedundancies(module.getResources()); 416 resourceSitePaths = removeNonAccessible(cmsClone, resourceSitePaths); 417 418 List<CmsResource> moduleResources = new ArrayList<CmsResource>(resourceSitePaths.size()); 419 for (String resourceSitePath : resourceSitePaths) { 420 // assumes resources are accessible - already checked aboveremoveNonAccessible 421 CmsResource resource = cmsClone.readResource(resourceSitePath); 422 moduleResources.add(resource); 423 } 424 425 if (excluded.isEmpty()) { 426 result = moduleResources; 427 } else { 428 result = new ArrayList<CmsResource>(); 429 430 addCalculatedModuleResources(result, cmsClone, moduleResources, excluded); 431 432 } 433 return result; 434 435 } 436 437 /** Adjusts the site root and returns a cloned CmsObject, iff the module has set an import site that differs 438 * from the site root of the CmsObject provided as argument. Otherwise returns the provided CmsObject unchanged. 439 * @param cms The original CmsObject. 440 * @param module The module where the import site is read from. 441 * @return The original CmsObject, or, if necessary, a clone with adjusted site root 442 * @throws CmsException see {@link OpenCms#initCmsObject(CmsObject)} 443 */ 444 private static CmsObject adjustSiteRootIfNecessary(final CmsObject cms, final CmsModule module) 445 throws CmsException { 446 447 CmsObject cmsClone; 448 if ((null == module.getImportSite()) || cms.getRequestContext().getSiteRoot().equals(module.getImportSite())) { 449 cmsClone = cms; 450 } else { 451 cmsClone = OpenCms.initCmsObject(cms); 452 cmsClone.getRequestContext().setSiteRoot(module.getImportSite()); 453 } 454 455 return cmsClone; 456 } 457 458 /** Returns only the resource names starting with the provided <code>sitePath</code>. 459 * 460 * @param sitePath the site relative path, all paths should start with. 461 * @param excluded the paths to filter. 462 * @return the paths from <code>excluded</code>, that start with <code>sitePath</code>. 463 */ 464 private static List<String> getExcludedForResource(final String sitePath, final List<String> excluded) { 465 466 List<String> result = new ArrayList<String>(); 467 for (String exclude : excluded) { 468 if (exclude.startsWith(sitePath)) { 469 result.add(exclude); 470 } 471 } 472 return result; 473 } 474 475 /** Removes the resources not accessible with the provided {@link CmsObject}. 476 * 477 * @param cms the {@link CmsObject} used to read the resources. 478 * @param sitePaths site relative paths of the resources that should be checked for accessibility. 479 * @return site paths of the accessible resources. 480 */ 481 private static List<String> removeNonAccessible(CmsObject cms, List<String> sitePaths) { 482 483 List<String> result = new ArrayList<String>(sitePaths.size()); 484 for (String sitePath : sitePaths) { 485 if (cms.existsResource(sitePath, CmsResourceFilter.ALL)) { 486 result.add(sitePath); 487 } 488 } 489 return result; 490 } 491 492 /** 493 * Checks if this module depends on another given module, 494 * will return the dependency, or <code>null</code> if no dependency was found.<p> 495 * 496 * @param module the other module to check against 497 * @return the dependency, or null if no dependency was found 498 */ 499 public CmsModuleDependency checkDependency(CmsModule module) { 500 501 CmsModuleDependency otherDepdendency = new CmsModuleDependency(module.getName(), module.getVersion()); 502 503 // loop through all the dependencies 504 for (int i = 0; i < m_dependencies.size(); i++) { 505 CmsModuleDependency dependency = m_dependencies.get(i); 506 if (dependency.dependesOn(otherDepdendency)) { 507 // short circuit here 508 return dependency; 509 } 510 } 511 512 // no dependency was found 513 return null; 514 } 515 516 /** 517 * Checks if all resources of the module are present.<p> 518 * 519 * @param cms an initialized OpenCms user context which must have read access to all module resources 520 * 521 * @throws CmsIllegalArgumentException in case not all module resources exist or can be read with the given OpenCms user context 522 */ 523 public void checkResources(CmsObject cms) throws CmsIllegalArgumentException { 524 525 CmsFileUtil.checkResources(cms, getResources()); 526 } 527 528 /** 529 * Clones a CmsModule which is not set to frozen.<p> 530 * This clones module can be used to be update the module information. 531 * 532 * @see java.lang.Object#clone() 533 */ 534 @Override 535 public Object clone() { 536 537 // create a copy of the module 538 CmsModule result = new CmsModule( 539 m_name, 540 m_niceName, 541 m_group, 542 m_actionClass, 543 m_importScript, 544 m_importSite, 545 m_exportMode, 546 m_description, 547 m_version, 548 m_authorName, 549 m_authorEmail, 550 m_dateCreated, 551 m_userInstalled, 552 m_dateInstalled, 553 m_dependencies, 554 m_exportPoints, 555 m_resources, 556 m_excluderesources, 557 m_parameters); 558 // and set its frozen state to false 559 result.m_frozen = false; 560 561 if (getExplorerTypes() != null) { 562 List<CmsExplorerTypeSettings> settings = new ArrayList<CmsExplorerTypeSettings>(); 563 for (CmsExplorerTypeSettings setting : getExplorerTypes()) { 564 settings.add((CmsExplorerTypeSettings)setting.clone()); 565 } 566 result.setExplorerTypes(settings); 567 } 568 if (getResourceTypes() != null) { 569 // TODO: The resource types must be cloned also, otherwise modification will effect the origin also 570 result.setResourceTypes(new ArrayList<I_CmsResourceType>(getResourceTypes())); 571 } 572 if (getDependencies() != null) { 573 List<CmsModuleDependency> deps = new ArrayList<CmsModuleDependency>(); 574 for (CmsModuleDependency dep : getDependencies()) { 575 deps.add((CmsModuleDependency)dep.clone()); 576 } 577 result.setDependencies(new ArrayList<CmsModuleDependency>(getDependencies())); 578 } 579 if (getExportPoints() != null) { 580 List<CmsExportPoint> exps = new ArrayList<CmsExportPoint>(); 581 for (CmsExportPoint exp : getExportPoints()) { 582 exps.add((CmsExportPoint)exp.clone()); 583 } 584 result.setExportPoints(exps); 585 } 586 587 result.setCreateClassesFolder(m_createClassesFolder); 588 result.setCreateElementsFolder(m_createElementsFolder); 589 result.setCreateLibFolder(m_createLibFolder); 590 result.setCreateModuleFolder(m_createModuleFolder); 591 result.setCreateResourcesFolder(m_createResourcesFolder); 592 result.setCreateSchemasFolder(m_createSchemasFolder); 593 result.setCreateTemplateFolder(m_createTemplateFolder); 594 result.setCreateFormattersFolder(m_createFormattersFolder); 595 596 result.setResources(new ArrayList<String>(m_resources)); 597 result.setExcludeResources(new ArrayList<String>(m_excluderesources)); 598 599 return result; 600 } 601 602 /** 603 * @see java.lang.Comparable#compareTo(java.lang.Object) 604 */ 605 public int compareTo(CmsModule obj) { 606 607 if (obj == this) { 608 return 0; 609 } 610 return m_name.compareTo(obj.m_name); 611 } 612 613 /** 614 * Two instances of a module are considered equal if their name is equal.<p> 615 * 616 * @param obj the object to compare 617 * 618 * @return true if the objects are equal 619 * 620 * @see java.lang.Object#equals(java.lang.Object) 621 * @see #isIdentical(CmsModule) 622 */ 623 @Override 624 public boolean equals(Object obj) { 625 626 if (obj == this) { 627 return true; 628 } 629 if (obj instanceof CmsModule) { 630 return ((CmsModule)obj).m_name.equals(m_name); 631 } 632 return false; 633 } 634 635 /** 636 * Returns the class name of this modules (optional) action class.<p> 637 * 638 * If this module does not use an action class, 639 * <code>null</code> is returned.<p> 640 * 641 * @return the class name of this modules (optional) action class 642 */ 643 public String getActionClass() { 644 645 return m_actionClass; 646 } 647 648 /** 649 * Returns the module action instance of this module, or <code>null</code> 650 * if no module action instance is configured.<p> 651 * 652 * @return the module action instance of this module 653 */ 654 public I_CmsModuleAction getActionInstance() { 655 656 return m_actionInstance; 657 } 658 659 /** 660 * Returns the email of the module author.<p> 661 * 662 * @return the email of the module author 663 */ 664 public String getAuthorEmail() { 665 666 return m_authorEmail; 667 } 668 669 /** 670 * Returns the name of the author of this module.<p> 671 * 672 * @return the name of the author of this module 673 */ 674 public String getAuthorName() { 675 676 return m_authorName; 677 } 678 679 /** 680 * Gets the module configuration path.<p> 681 * 682 * @return the module configuration path 683 */ 684 public String getConfigurationPath() { 685 686 String parameter = getParameter("config.sitemap"); 687 if (parameter != null) { 688 return parameter; 689 } else { 690 return "/system/modules/" + getName() + "/.config"; 691 } 692 } 693 694 /** 695 * Returns the date this module was created by the author.<p> 696 * 697 * @return the date this module was created by the author 698 */ 699 public long getDateCreated() { 700 701 return m_dateCreated; 702 } 703 704 /** 705 * Returns the date this module was uploaded.<p> 706 * 707 * @return the date this module was uploaded 708 */ 709 public long getDateInstalled() { 710 711 return m_dateInstalled; 712 } 713 714 /** 715 * Returns the list of dependencies of this module.<p> 716 * 717 * @return the list of dependencies of this module 718 */ 719 public List<CmsModuleDependency> getDependencies() { 720 721 return m_dependencies; 722 } 723 724 /** 725 * Returns the description of this module.<p> 726 * 727 * @return the description of this module 728 */ 729 public String getDescription() { 730 731 return m_description; 732 } 733 734 /** 735 * Returns the list of VFS resources that do not belong to this module.<p> 736 * In particular, files / folders that would be included otherwise, 737 * considering the module resources.<p> 738 * 739 * @return the list of VFS resources that do not belong to this module 740 */ 741 public List<String> getExcludeResources() { 742 743 return m_excluderesources; 744 } 745 746 /** 747 * Returns the list of explorer resource types that belong to this module.<p> 748 * 749 * @return the list of explorer resource types that belong to this module 750 */ 751 public List<CmsExplorerTypeSettings> getExplorerTypes() { 752 753 return m_explorerTypeSettings; 754 } 755 756 /** Returns the export mode specified for the module. 757 * @return the module's export mode. 758 */ 759 public ExportMode getExportMode() { 760 761 return m_exportMode; 762 } 763 764 /** 765 * Returns the list of export point added by this module.<p> 766 * 767 * @return the list of export point added by this module 768 */ 769 public List<CmsExportPoint> getExportPoints() { 770 771 return m_exportPoints; 772 } 773 774 /** 775 * Returns the group name of this module.<p> 776 * 777 * @return the group name of this module 778 */ 779 public String getGroup() { 780 781 return m_group; 782 } 783 784 /** 785 * Returns the importScript.<p> 786 * 787 * @return the importScript 788 */ 789 public String getImportScript() { 790 791 return m_importScript; 792 } 793 794 /** 795 * Gets the import site.<p> 796 * 797 * If this is not empty, then it will be used as the site root for importing and exporting this module.<p> 798 * 799 * @return the import site 800 */ 801 public String getImportSite() { 802 803 return m_importSite; 804 } 805 806 /** 807 * Returns the name of this module.<p> 808 * 809 * The module name must be a valid java package name.<p> 810 * 811 * @return the name of this module 812 */ 813 public String getName() { 814 815 return m_name; 816 } 817 818 /** 819 * Returns the "nice" display name of this module.<p> 820 * 821 * @return the "nice" display name of this module 822 */ 823 public String getNiceName() { 824 825 return m_niceName; 826 } 827 828 /** 829 * Gets the timestamp of this object's creation time.<p> 830 * 831 * @return the object creation timestamp 832 */ 833 public long getObjectCreateTime() { 834 835 return m_objectCreateTime; 836 } 837 838 /** 839 * Returns a parameter value from the module parameters.<p> 840 * 841 * @param key the parameter to return the value for 842 * @return the parameter value from the module parameters 843 */ 844 public String getParameter(String key) { 845 846 return m_parameters.get(key); 847 } 848 849 /** 850 * Returns a parameter value from the module parameters, 851 * or a given default value in case the parameter is not set.<p> 852 * 853 * @param key the parameter to return the value for 854 * @param defaultValue the default value in case there is no value stored for this key 855 * @return the parameter value from the module parameters 856 */ 857 public String getParameter(String key, String defaultValue) { 858 859 String value = m_parameters.get(key); 860 return (value != null) ? value : defaultValue; 861 } 862 863 /** 864 * Returns the configured (immutable) module parameters.<p> 865 * 866 * @return the configured (immutable) module parameters 867 */ 868 public SortedMap<String, String> getParameters() { 869 870 return m_parameters; 871 } 872 873 /** 874 * Returns the list of VFS resources that belong to this module.<p> 875 * 876 * @return the list of VFS resources that belong to this module 877 */ 878 public List<String> getResources() { 879 880 return m_resources; 881 } 882 883 /** 884 * Returns the list of additional resource types that belong to this module.<p> 885 * 886 * @return the list of additional resource types that belong to this module 887 */ 888 public List<I_CmsResourceType> getResourceTypes() { 889 890 return m_resourceTypes; 891 } 892 893 /** 894 * Returns the name of the user who uploaded this module.<p> 895 * 896 * @return the name of the user who uploaded this module 897 */ 898 public String getUserInstalled() { 899 900 return m_userInstalled; 901 } 902 903 /** 904 * Returns the version of this module.<p> 905 * 906 * @return the version of this module 907 */ 908 public CmsModuleVersion getVersion() { 909 910 return m_version; 911 } 912 913 /** 914 * @see java.lang.Object#hashCode() 915 */ 916 @Override 917 public int hashCode() { 918 919 return m_name.hashCode(); 920 } 921 922 /** 923 * Returns the createClassesFolder flag.<p> 924 * 925 * @return the createClassesFolder flag 926 */ 927 public boolean isCreateClassesFolder() { 928 929 return m_createClassesFolder; 930 } 931 932 /** 933 * Returns the createElementsFolder flag.<p> 934 * 935 * @return the createElementsFolder flag 936 */ 937 public boolean isCreateElementsFolder() { 938 939 return m_createElementsFolder; 940 } 941 942 /** 943 * Returns the createFormattersFolder flag.<p> 944 * 945 * @return the createFormattersFolder flag 946 */ 947 public boolean isCreateFormattersFolder() { 948 949 return m_createFormattersFolder; 950 } 951 952 /** 953 * Returns the createLibFolder flag.<p> 954 * 955 * @return the createLibFolder flag 956 */ 957 public boolean isCreateLibFolder() { 958 959 return m_createLibFolder; 960 } 961 962 /** 963 * Returns the createModuleFolder flag.<p> 964 * 965 * @return the createModuleFolder flag 966 */ 967 public boolean isCreateModuleFolder() { 968 969 return m_createModuleFolder; 970 } 971 972 /** 973 * Returns the createResourcesFolder flag.<p> 974 * 975 * @return the createResourcesFolder flag 976 */ 977 public boolean isCreateResourcesFolder() { 978 979 return m_createResourcesFolder; 980 } 981 982 /** 983 * Returns the createSchemasFolder flag.<p> 984 * 985 * @return the createSchemasFolder flag 986 */ 987 public boolean isCreateSchemasFolder() { 988 989 return m_createSchemasFolder; 990 } 991 992 /** 993 * Returns the createTemplateFolder flag.<p> 994 * 995 * @return the createTemplateFolder flag 996 */ 997 public boolean isCreateTemplateFolder() { 998 999 return m_createTemplateFolder; 1000 } 1001 1002 /** 1003 * Checks if this module is identical with another module.<p> 1004 * 1005 * Modules A, B are <b>identical</b> if <i>all</i> values of A are equal to B. 1006 * The values from {@link #getUserInstalled()} and {@link #getDateInstalled()} 1007 * are ignored for this test.<p> 1008 * 1009 * Modules A, B are <b>equal</b> if just the name of A is equal to the name of B.<p> 1010 * 1011 * @param other the module to compare with 1012 * 1013 * @return if the modules are identical 1014 * 1015 * @see #equals(Object) 1016 */ 1017 public boolean isIdentical(CmsModule other) { 1018 1019 // some code redundancy here but this is easier to debug 1020 if (!isEqual(m_name, other.m_name)) { 1021 return false; 1022 } 1023 if (!isEqual(m_niceName, other.m_niceName)) { 1024 return false; 1025 } 1026 if (!isEqual(m_version, other.m_version)) { 1027 return false; 1028 } 1029 if (!isEqual(m_actionClass, other.m_actionClass)) { 1030 return false; 1031 } 1032 if (!isEqual(m_description, other.m_description)) { 1033 return false; 1034 } 1035 if (!isEqual(m_authorName, other.m_authorName)) { 1036 return false; 1037 } 1038 if (!isEqual(m_authorEmail, other.m_authorEmail)) { 1039 return false; 1040 } 1041 if (m_dateCreated != other.m_dateCreated) { 1042 return false; 1043 } 1044 return true; 1045 } 1046 1047 /** Checks, if the module should use the reduced export mode. 1048 * @return if reduce export mode should be used <code>true</code>, otherwise <code>false</code>. 1049 */ 1050 public boolean isReducedExportMode() { 1051 1052 return ExportMode.REDUCED.equals(m_exportMode); 1053 } 1054 1055 /** 1056 * Sets the class name of this modules (optional) action class.<p> 1057 * 1058 * Providing <code>null</code> as a value indicates that this module does not use an action class.<p> 1059 * 1060 * <i>Please note:</i>It's not possible to set the action class name once the module 1061 * configuration has been frozen.<p> 1062 * 1063 * @param value the class name of this modules (optional) action class to set 1064 */ 1065 public void setActionClass(String value) { 1066 1067 checkFrozen(); 1068 if (CmsStringUtil.isEmpty(value)) { 1069 m_actionClass = null; 1070 } else { 1071 if (!CmsStringUtil.isValidJavaClassName(value)) { 1072 throw new CmsIllegalArgumentException( 1073 Messages.get().container(Messages.ERR_MODULE_ACTION_CLASS_2, value, getName())); 1074 } 1075 m_actionClass = value; 1076 } 1077 } 1078 1079 /** 1080 * Sets the author email of this module.<p> 1081 * 1082 * 1083 * <i>Please note:</i>It's not possible to set the modules author email once the module 1084 * configuration has been frozen.<p> 1085 * 1086 * @param value the module description to set 1087 */ 1088 public void setAuthorEmail(String value) { 1089 1090 checkFrozen(); 1091 m_authorEmail = value.trim(); 1092 } 1093 1094 /** 1095 * Sets the author name of this module.<p> 1096 * 1097 * 1098 * <i>Please note:</i>It's not possible to set the modules author name once the module 1099 * configuration has been frozen.<p> 1100 * 1101 * @param value the module description to set 1102 */ 1103 public void setAuthorName(String value) { 1104 1105 checkFrozen(); 1106 m_authorName = value.trim(); 1107 } 1108 1109 /** 1110 * Sets the createClassesFolder flag.<p> 1111 * 1112 * @param createClassesFolder the createClassesFolder flag to set 1113 */ 1114 public void setCreateClassesFolder(boolean createClassesFolder) { 1115 1116 m_createClassesFolder = createClassesFolder; 1117 } 1118 1119 /** 1120 * Sets the createElementsFolder flag.<p> 1121 * 1122 * @param createElementsFolder the createElementsFolder flag to set 1123 */ 1124 public void setCreateElementsFolder(boolean createElementsFolder) { 1125 1126 m_createElementsFolder = createElementsFolder; 1127 } 1128 1129 /** 1130 * Sets the createFormattersFolder flag.<p> 1131 * 1132 * @param createFormattersFolder the createFormattersFolder flag to set 1133 */ 1134 public void setCreateFormattersFolder(boolean createFormattersFolder) { 1135 1136 m_createFormattersFolder = createFormattersFolder; 1137 } 1138 1139 /** 1140 * Sets the createLibFolder flag.<p> 1141 * 1142 * @param createLibFolder the createLibFolder flag to set 1143 */ 1144 public void setCreateLibFolder(boolean createLibFolder) { 1145 1146 m_createLibFolder = createLibFolder; 1147 } 1148 1149 /** 1150 * Sets the createModuleFolder flag.<p> 1151 * 1152 * @param createModuleFolder the createModuleFolder flag to set 1153 */ 1154 public void setCreateModuleFolder(boolean createModuleFolder) { 1155 1156 m_createModuleFolder = createModuleFolder; 1157 } 1158 1159 /** 1160 * Sets the createResourcesFolder flag.<p> 1161 * 1162 * @param createResourcesFolder the createResourcesFolder flag to set 1163 */ 1164 public void setCreateResourcesFolder(boolean createResourcesFolder) { 1165 1166 m_createResourcesFolder = createResourcesFolder; 1167 } 1168 1169 /** 1170 * Sets the createSchemasFolder flag .<p> 1171 * 1172 * @param createSchemasFolder the createSchemasFolder flag to set 1173 */ 1174 public void setCreateSchemasFolder(boolean createSchemasFolder) { 1175 1176 m_createSchemasFolder = createSchemasFolder; 1177 } 1178 1179 /** 1180 * Sets the createTemplateFolder flag .<p> 1181 * 1182 * @param createTemplateFolder the createTemplateFolder flag to set 1183 */ 1184 public void setCreateTemplateFolder(boolean createTemplateFolder) { 1185 1186 m_createTemplateFolder = createTemplateFolder; 1187 } 1188 1189 /** 1190 * Sets the date created of this module.<p> 1191 * 1192 * 1193 * <i>Please note:</i>It's not possible to set the module date created once the module 1194 * configuration has been frozen.<p> 1195 * 1196 * @param value the date created to set 1197 */ 1198 public void setDateCreated(long value) { 1199 1200 checkFrozen(); 1201 m_dateCreated = value; 1202 } 1203 1204 /** 1205 * Sets the installation date of this module.<p> 1206 * 1207 * 1208 * <i>Please note:</i>It's not possible to set the installation date once the module 1209 * configuration has been frozen.<p> 1210 * 1211 * @param value the installation date this module 1212 */ 1213 public void setDateInstalled(long value) { 1214 1215 checkFrozen(); 1216 m_dateInstalled = value; 1217 } 1218 1219 /** 1220 * Sets the list of module dependencies.<p> 1221 * 1222 * @param dependencies list of module dependencies 1223 */ 1224 public void setDependencies(List<CmsModuleDependency> dependencies) { 1225 1226 checkFrozen(); 1227 m_dependencies = dependencies; 1228 } 1229 1230 /** 1231 * Sets the description of this module.<p> 1232 * 1233 * 1234 * <i>Please note:</i>It's not possible to set the modules description once the module 1235 * configuration has been frozen.<p> 1236 * 1237 * @param value the module description to set 1238 */ 1239 public void setDescription(String value) { 1240 1241 checkFrozen(); 1242 m_description = value.trim(); 1243 } 1244 1245 /** 1246 * Sets the resources excluded from this module.<p> 1247 * 1248 * 1249 * <i>Please note:</i>It's not possible to set the module resources once the module 1250 * configuration has been frozen.<p> 1251 * 1252 * @param value the resources to exclude from the module 1253 */ 1254 public void setExcludeResources(List<String> value) { 1255 1256 checkFrozen(); 1257 m_excluderesources = value; 1258 } 1259 1260 /** 1261 * Sets the additional explorer types that belong to this module.<p> 1262 * 1263 * @param explorerTypeSettings the explorer type settings. 1264 */ 1265 public void setExplorerTypes(List<CmsExplorerTypeSettings> explorerTypeSettings) { 1266 1267 m_explorerTypeSettings = explorerTypeSettings; 1268 } 1269 1270 /** 1271 * Sets the export points of this module.<p> 1272 * 1273 * @param exportPoints the export points of this module. 1274 */ 1275 public void setExportPoints(List<CmsExportPoint> exportPoints) { 1276 1277 m_exportPoints = exportPoints; 1278 } 1279 1280 /** 1281 * Sets the group name of this module.<p> 1282 * 1283 * 1284 * <i>Please note:</i>It's not possible to set the modules group name once the module 1285 * configuration has been frozen.<p> 1286 * 1287 * @param value the module group name to set 1288 */ 1289 public void setGroup(String value) { 1290 1291 checkFrozen(); 1292 m_group = value; 1293 } 1294 1295 /** 1296 * Sets the importScript.<p> 1297 * 1298 * @param importScript the importScript to set 1299 */ 1300 public void setImportScript(String importScript) { 1301 1302 checkFrozen(); 1303 m_importScript = importScript; 1304 } 1305 1306 /** 1307 * Sets the import site.<p> 1308 * 1309 * @param importSite the import site 1310 */ 1311 public void setImportSite(String importSite) { 1312 1313 checkFrozen(); 1314 if (importSite != null) { 1315 importSite = importSite.trim(); 1316 } 1317 m_importSite = importSite; 1318 } 1319 1320 /** 1321 * Sets the name of this module.<p> 1322 * 1323 * The module name must be a valid java package name.<p> 1324 * 1325 * <i>Please note:</i>It's not possible to set the modules name once the module 1326 * configuration has been frozen.<p> 1327 * 1328 * @param value the module name to set 1329 */ 1330 public void setName(String value) { 1331 1332 checkFrozen(); 1333 if (!CmsStringUtil.isValidJavaClassName(value)) { 1334 throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_MODULE_NAME_1, value)); 1335 } 1336 m_name = value; 1337 } 1338 1339 /** 1340 * Sets the "nice" display name of this module.<p> 1341 * 1342 * <i>Please note:</i>It's not possible to set the modules "nice" name once the module 1343 * configuration has been frozen.<p> 1344 * 1345 * @param value the "nice" display name of this module to set 1346 */ 1347 public void setNiceName(String value) { 1348 1349 checkFrozen(); 1350 if (CmsStringUtil.isEmptyOrWhitespaceOnly(value)) { 1351 m_niceName = getName(); 1352 } else { 1353 m_niceName = value.trim(); 1354 } 1355 } 1356 1357 /** 1358 * Sets the parameters of this module.<p> 1359 * 1360 * 1361 * <i>Please note:</i>It's not possible to set the module parameters once the module 1362 * configuration has been frozen.<p> 1363 * 1364 * @param parameters the module parameters to set 1365 */ 1366 public void setParameters(SortedMap<String, String> parameters) { 1367 1368 checkFrozen(); 1369 m_parameters = parameters; 1370 } 1371 1372 /** Set/unset the reduced export mode. 1373 * @param reducedExportMode if <code>true</code>, the export mode is set to {@link ExportMode#REDUCED}, otherwise to {@link ExportMode#DEFAULT}. 1374 */ 1375 public void setReducedExportMode(boolean reducedExportMode) { 1376 1377 m_exportMode = reducedExportMode ? ExportMode.REDUCED : ExportMode.DEFAULT; 1378 } 1379 1380 /** 1381 * Sets the resources of this module.<p> 1382 * 1383 * 1384 * <i>Please note:</i>It's not possible to set the module resources once the module 1385 * configuration has been frozen.<p> 1386 * 1387 * @param value the module resources to set 1388 */ 1389 public void setResources(List<String> value) { 1390 1391 checkFrozen(); 1392 m_resources = value; 1393 } 1394 1395 /** 1396 * Sets the list of additional resource types that belong to this module.<p> 1397 * 1398 * @param resourceTypes list of additional resource types that belong to this module 1399 */ 1400 public void setResourceTypes(List<I_CmsResourceType> resourceTypes) { 1401 1402 m_resourceTypes = Collections.unmodifiableList(resourceTypes); 1403 } 1404 1405 /** 1406 * Sets the user who installed of this module.<p> 1407 * 1408 * 1409 * <i>Please note:</i>It's not possible to set the user installed once the module 1410 * configuration has been frozen.<p> 1411 * 1412 * @param value the user who installed this module 1413 */ 1414 public void setUserInstalled(String value) { 1415 1416 checkFrozen(); 1417 m_userInstalled = value.trim(); 1418 } 1419 1420 /** 1421 * Checks if this modules configuration is frozen.<p> 1422 * 1423 * @throws CmsIllegalArgumentException in case the configuration is already frozen 1424 */ 1425 protected void checkFrozen() throws CmsIllegalArgumentException { 1426 1427 if (m_frozen) { 1428 throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_MODULE_FROZEN_1, getName())); 1429 } 1430 } 1431 1432 /** 1433 * Initializes this module, also freezing the module configuration.<p> 1434 * 1435 * @param cms an initialized OpenCms user context 1436 * 1437 * @throws CmsRoleViolationException if the given users does not have the <code>{@link CmsRole#DATABASE_MANAGER}</code> role 1438 */ 1439 protected void initialize(CmsObject cms) throws CmsRoleViolationException { 1440 1441 checkFrozen(); 1442 // check if the user has the required permissions 1443 OpenCms.getRoleManager().checkRole(cms, CmsRole.DATABASE_MANAGER); 1444 1445 m_frozen = true; 1446 m_resources = Collections.unmodifiableList(m_resources); 1447 m_excluderesources = Collections.unmodifiableList(m_excluderesources); 1448 } 1449 1450 /** 1451 * Sets the module action instance for this module.<p> 1452 * 1453 * @param actionInstance the module action instance for this module 1454 */ 1455 /*package*/void setActionInstance(I_CmsModuleAction actionInstance) { 1456 1457 m_actionInstance = actionInstance; 1458 1459 } 1460 1461 /** 1462 * Resolves the module property "additionalresources" to the resource list and 1463 * vice versa.<p> 1464 * 1465 * This "special" module property is required as long as we do not have a new 1466 * GUI for editing of module resource entries. Once we have the new GUI, the 1467 * handling of "additionalresources" will be moved to the import of the module 1468 * and done only if the imported module is a 5.0 module.<p> 1469 */ 1470 private void initOldAdditionalResources() { 1471 1472 SortedMap<String, String> parameters = new TreeMap<String, String>(m_parameters); 1473 List<String> resources = new ArrayList<String>(m_resources); 1474 1475 String additionalResources; 1476 additionalResources = parameters.get(MODULE_PROPERTY_ADDITIONAL_RESOURCES); 1477 if (additionalResources != null) { 1478 StringTokenizer tok = new StringTokenizer( 1479 additionalResources, 1480 MODULE_PROPERTY_ADDITIONAL_RESOURCES_SEPARATOR); 1481 while (tok.hasMoreTokens()) { 1482 String resource = tok.nextToken().trim(); 1483 if ((!"-".equals(resource)) && (!resources.contains(resource))) { 1484 resources.add(resource); 1485 } 1486 } 1487 } 1488 1489 m_resources = resources; 1490 } 1491 1492 /** 1493 * Checks if two objects are either both null, or equal.<p> 1494 * 1495 * @param a the first object to check 1496 * @param b the second object to check 1497 * @return true if the two object are either both null, or equal 1498 */ 1499 private boolean isEqual(Object a, Object b) { 1500 1501 if (a == null) { 1502 return (b == null); 1503 } 1504 if (b == null) { 1505 return false; 1506 } 1507 return a.equals(b); 1508 } 1509}