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.types.I_CmsResourceType;
033import org.opencms.main.CmsIllegalArgumentException;
034import org.opencms.main.CmsLog;
035import org.opencms.main.OpenCms;
036import org.opencms.security.CmsRole;
037import org.opencms.security.CmsRoleViolationException;
038import org.opencms.util.CmsFileUtil;
039import org.opencms.util.CmsStringUtil;
040import org.opencms.workplace.explorer.CmsExplorerTypeSettings;
041
042import java.util.ArrayList;
043import java.util.Collections;
044import java.util.List;
045import java.util.Map;
046import java.util.SortedMap;
047import java.util.StringTokenizer;
048import java.util.TreeMap;
049
050import org.apache.commons.logging.Log;
051
052/**
053 * Describes an OpenCms module.<p>
054 * 
055 * OpenCms modules provide a standard mechanism to extend the OpenCms functionality.
056 * Modules can contain VFS data, Java classes and a number of configuration options.<p> 
057 * 
058 * @since 6.0.0 
059 * 
060 * @see org.opencms.module.I_CmsModuleAction
061 * @see org.opencms.module.A_CmsModuleAction
062 */
063public class CmsModule implements Comparable<CmsModule> {
064
065    /** The default date for module created / installed if not provided. */
066    public static final long DEFAULT_DATE = 0L;
067
068    /** The log object for this class. */
069    private static final Log LOG = CmsLog.getLog(CmsModule.class);
070
071    /**
072     * The module property key name to specifiy additional resources which are
073     * part of a module outside of {system/modules}.
074     */
075    private static final String MODULE_PROPERTY_ADDITIONAL_RESOURCES = "additionalresources";
076
077    /** Character to separate additional resources specified in the module properties.  */
078    private static final String MODULE_PROPERTY_ADDITIONAL_RESOURCES_SEPARATOR = ";";
079
080    /** The module action class name. */
081    private String m_actionClass;
082
083    /** Initialized module action instance. */
084    private I_CmsModuleAction m_actionInstance;
085
086    /** The email of the author of this module. */
087    private String m_authorEmail;
088
089    /** The name of the author of this module. */
090    private String m_authorName;
091
092    /** Flag to create the classes folders when creating the module. */
093    private boolean m_createClassesFolder;
094
095    /** Flag to create the elements folder when creating the module. */
096    private boolean m_createElementsFolder;
097
098    /** Flag to create the formatters folder when creating the module. */
099    private boolean m_createFormattersFolder;
100
101    /** Flag to create the lib folder when creating the module. */
102    private boolean m_createLibFolder;
103
104    /** Flag to create the module folder when creating the module. */
105    private boolean m_createModuleFolder;
106
107    /** Flag to create the resources folder when creating the module. */
108    private boolean m_createResourcesFolder;
109
110    /** Flag to create the schemas folder when creating the module. */
111    private boolean m_createSchemasFolder;
112
113    /** Flag to create the template folder when creating the module. */
114    private boolean m_createTemplateFolder;
115
116    /** The date this module was created by the author. */
117    private long m_dateCreated;
118
119    /** The date this module was installed. */
120    private long m_dateInstalled;
121
122    /** List of dependencies of this module. */
123    private List<CmsModuleDependency> m_dependencies;
124
125    /** The description of this module. */
126    private String m_description;
127
128    /** The explorer type settings. */
129    private List<CmsExplorerTypeSettings> m_explorerTypeSettings;
130
131    /** List of export points added by this module. */
132    private List<CmsExportPoint> m_exportPoints;
133
134    /** Indicates if this modules configuration has already been frozen. */
135    private boolean m_frozen;
136
137    /** The group of the module. */
138    private String m_group;
139
140    /** The name of this module, must be a valid Java package name. */
141    private String m_name;
142
143    /** The "nice" display name of this module. */
144    private String m_niceName;
145
146    /** The additional configuration parameters of this module. */
147    private SortedMap<String, String> m_parameters;
148
149    /** List of VFS resources that belong to this module. */
150    private List<String> m_resources;
151
152    /** The list of additional resource types. */
153    private List<I_CmsResourceType> m_resourceTypes;
154
155    /** The name of the user who installed this module. */
156    private String m_userInstalled;
157
158    /** The version of this module. */
159    private CmsModuleVersion m_version;
160
161    /**
162     * Creates a new, empty CmsModule object.<p>
163     */
164    public CmsModule() {
165
166        m_version = new CmsModuleVersion(CmsModuleVersion.DEFAULT_VERSION);
167        m_resources = Collections.emptyList();
168        m_exportPoints = Collections.emptyList();
169        m_dependencies = Collections.emptyList();
170    }
171
172    /**
173     * Creates a new module description with the specified values.<p>
174     * 
175     * @param name the name of this module, must be a valid Java package name
176     * @param niceName the "nice" display name of this module
177     * @param group the group of this module
178     * @param actionClass the (optional) module class name
179     * @param description the description of this module
180     * @param version the version of this module
181     * @param authorName the name of the author of this module
182     * @param authorEmail the email of the author of this module
183     * @param dateCreated the date this module was created by the author
184     * @param userInstalled the name of the user who uploaded this module
185     * @param dateInstalled the date this module was uploaded
186     * @param dependencies a list of dependencies of this module
187     * @param exportPoints a list of export point added by this module
188     * @param resources a list of VFS resources that belong to this module
189     * @param parameters the parameters for this module
190     */
191    public CmsModule(
192        String name,
193        String niceName,
194        String group,
195        String actionClass,
196        String description,
197        CmsModuleVersion version,
198        String authorName,
199        String authorEmail,
200        long dateCreated,
201        String userInstalled,
202        long dateInstalled,
203        List<CmsModuleDependency> dependencies,
204        List<CmsExportPoint> exportPoints,
205        List<String> resources,
206        Map<String, String> parameters) {
207
208        super();
209        m_name = name;
210        setNiceName(niceName);
211        setActionClass(actionClass);
212        setGroup(group);
213
214        if (CmsStringUtil.isEmpty(description)) {
215            m_description = "";
216        } else {
217            m_description = description;
218        }
219        m_version = version;
220        if (CmsStringUtil.isEmpty(authorName)) {
221            m_authorName = "";
222        } else {
223            m_authorName = authorName;
224        }
225        if (CmsStringUtil.isEmpty(authorEmail)) {
226            m_authorEmail = "";
227        } else {
228            m_authorEmail = authorEmail;
229        }
230        // remove milisecounds
231        m_dateCreated = (dateCreated / 1000L) * 1000L;
232        if (CmsStringUtil.isEmpty(userInstalled)) {
233            m_userInstalled = "";
234        } else {
235            m_userInstalled = userInstalled;
236        }
237        m_dateInstalled = (dateInstalled / 1000L) * 1000L;
238        if (dependencies == null) {
239            m_dependencies = Collections.emptyList();
240        } else {
241            m_dependencies = Collections.unmodifiableList(dependencies);
242        }
243        if (exportPoints == null) {
244            m_exportPoints = Collections.emptyList();
245        } else {
246            m_exportPoints = Collections.unmodifiableList(exportPoints);
247        }
248        if (resources == null) {
249            m_resources = Collections.emptyList();
250        } else {
251            m_resources = Collections.unmodifiableList(resources);
252        }
253        if (parameters == null) {
254            m_parameters = new TreeMap<String, String>();
255        } else {
256            m_parameters = new TreeMap<String, String>(parameters);
257        }
258
259        initOldAdditionalResources();
260
261        if (LOG.isDebugEnabled()) {
262            LOG.debug(Messages.get().getBundle().key(Messages.LOG_MODULE_INSTANCE_CREATED_1, m_name));
263        }
264        m_resourceTypes = Collections.emptyList();
265        m_explorerTypeSettings = Collections.emptyList();
266    }
267
268    /**
269     * Checks if this module depends on another given module,
270     * will return the dependency, or <code>null</code> if no dependency was found.<p>
271     * 
272     * @param module the other module to check against
273     * @return the dependency, or null if no dependency was found
274     */
275    public CmsModuleDependency checkDependency(CmsModule module) {
276
277        CmsModuleDependency otherDepdendency = new CmsModuleDependency(module.getName(), module.getVersion());
278
279        // loop through all the dependencies
280        for (int i = 0; i < m_dependencies.size(); i++) {
281            CmsModuleDependency dependency = m_dependencies.get(i);
282            if (dependency.dependesOn(otherDepdendency)) {
283                // short circuit here
284                return dependency;
285            }
286        }
287
288        // no dependency was found
289        return null;
290    }
291
292    /**
293     * Checks if all resources of the module are present.<p>
294     * 
295     * @param cms an initialized OpenCms user context which must have read access to all module resources
296     * 
297     * @throws CmsIllegalArgumentException in case not all module resources exist or can be read with the given OpenCms user context
298     */
299    public void checkResources(CmsObject cms) throws CmsIllegalArgumentException {
300
301        CmsFileUtil.checkResources(cms, getResources());
302    }
303
304    /**
305     * Clones a CmsModule which is not set to frozen.<p>
306     * This clones module can be used to be update the module information.
307     * 
308     * @see java.lang.Object#clone()
309     */
310    @Override
311    public Object clone() {
312
313        // create a copy of the module
314        CmsModule result = new CmsModule(
315            m_name,
316            m_niceName,
317            m_group,
318            m_actionClass,
319            m_description,
320            m_version,
321            m_authorName,
322            m_authorEmail,
323            m_dateCreated,
324            m_userInstalled,
325            m_dateInstalled,
326            m_dependencies,
327            m_exportPoints,
328            m_resources,
329            m_parameters);
330        // and set its frozen state to false
331        result.m_frozen = false;
332
333        if (getExplorerTypes() != null) {
334            List<CmsExplorerTypeSettings> settings = new ArrayList<CmsExplorerTypeSettings>();
335            for (CmsExplorerTypeSettings setting : getExplorerTypes()) {
336                settings.add((CmsExplorerTypeSettings)setting.clone());
337            }
338            result.setExplorerTypes(settings);
339        }
340        if (getResourceTypes() != null) {
341            // TODO: The resource types must be cloned also, otherwise modification will effect the origin also
342            result.setResourceTypes(new ArrayList<I_CmsResourceType>(getResourceTypes()));
343        }
344        if (getDependencies() != null) {
345            List<CmsModuleDependency> deps = new ArrayList<CmsModuleDependency>();
346            for (CmsModuleDependency dep : getDependencies()) {
347                deps.add((CmsModuleDependency)dep.clone());
348            }
349            result.setDependencies(new ArrayList<CmsModuleDependency>(getDependencies()));
350        }
351        if (getExportPoints() != null) {
352            List<CmsExportPoint> exps = new ArrayList<CmsExportPoint>();
353            for (CmsExportPoint exp : getExportPoints()) {
354                exps.add((CmsExportPoint)exp.clone());
355            }
356            result.setExportPoints(exps);
357        }
358
359        result.setCreateClassesFolder(m_createClassesFolder);
360        result.setCreateElementsFolder(m_createElementsFolder);
361        result.setCreateLibFolder(m_createLibFolder);
362        result.setCreateModuleFolder(m_createModuleFolder);
363        result.setCreateResourcesFolder(m_createResourcesFolder);
364        result.setCreateSchemasFolder(m_createSchemasFolder);
365        result.setCreateTemplateFolder(m_createTemplateFolder);
366        result.setCreateFormattersFolder(m_createFormattersFolder);
367
368        result.setResources(new ArrayList<String>(m_resources));
369
370        return result;
371    }
372
373    /**
374     * @see java.lang.Comparable#compareTo(java.lang.Object)
375     */
376    public int compareTo(CmsModule obj) {
377
378        if (obj == this) {
379            return 0;
380        }
381        return m_name.compareTo(obj.m_name);
382    }
383
384    /**
385     * Two instances of a module are considered equal if their name is equal.<p>
386     *
387     * @param obj the object to compare
388     * 
389     * @return true if the objects are equal
390     *  
391     * @see java.lang.Object#equals(java.lang.Object)
392     * @see #isIdentical(CmsModule)
393     */
394    @Override
395    public boolean equals(Object obj) {
396
397        if (obj == this) {
398            return true;
399        }
400        if (obj instanceof CmsModule) {
401            return ((CmsModule)obj).m_name.equals(m_name);
402        }
403        return false;
404    }
405
406    /**
407     * Returns the class name of this modules (optional) action class.<p>
408     *
409     * If this module does not use an action class,
410     * <code>null</code> is returned.<p>
411     *
412     * @return the class name of this modules (optional) action class
413     */
414    public String getActionClass() {
415
416        return m_actionClass;
417    }
418
419    /**
420     * Returns the module action instance of this module, or <code>null</code>
421     * if no module action instance is configured.<p>
422     * 
423     * @return the module action instance of this module
424     */
425    public I_CmsModuleAction getActionInstance() {
426
427        return m_actionInstance;
428    }
429
430    /**
431     * Returns the email of the module author.<p>
432     *
433     * @return the email of the module author
434     */
435    public String getAuthorEmail() {
436
437        return m_authorEmail;
438    }
439
440    /**
441     * Returns the name of the author of this module.<p>
442     *
443     * @return the name of the author of this module
444     */
445    public String getAuthorName() {
446
447        return m_authorName;
448    }
449
450    /**
451     * Gets the module configuration path.<p>
452     * 
453     * @return the module configuration path
454     */
455    public String getConfigurationPath() {
456
457        String parameter = getParameter("config.sitemap");
458        if (parameter != null) {
459            return parameter;
460        } else {
461            return "/system/modules/" + getName() + "/.config";
462        }
463    }
464
465    /**
466     * Returns the date this module was created by the author.<p>
467     *
468     * @return the date this module was created by the author
469     */
470    public long getDateCreated() {
471
472        return m_dateCreated;
473    }
474
475    /**
476     * Returns the date this module was uploaded.<p>
477     *
478     * @return the date this module was uploaded
479     */
480    public long getDateInstalled() {
481
482        return m_dateInstalled;
483    }
484
485    /**
486     * Returns the list of dependencies of this module.<p>
487     *
488     * @return the list of dependencies of this module
489     */
490    public List<CmsModuleDependency> getDependencies() {
491
492        return m_dependencies;
493    }
494
495    /**
496     * Returns the description of this module.<p>
497     *
498     * @return the description of this module
499     */
500    public String getDescription() {
501
502        return m_description;
503    }
504
505    /**
506     * Returns the list of explorer resource types that belong to this module.<p>
507     *
508     * @return the list of explorer resource types that belong to this module
509     */
510    public List<CmsExplorerTypeSettings> getExplorerTypes() {
511
512        return m_explorerTypeSettings;
513    }
514
515    /**
516     * Returns the list of export point added by this module.<p>
517     *
518     * @return the list of export point added by this module
519     */
520    public List<CmsExportPoint> getExportPoints() {
521
522        return m_exportPoints;
523    }
524
525    /**
526     * Returns the group name of this module.<p>
527     *
528     * @return the group name of this module
529     */
530    public String getGroup() {
531
532        return m_group;
533    }
534
535    /**
536     * Returns the name of this module.<p>
537     * 
538     * The module name must be a valid java package name.<p>
539     *
540     * @return the name of this module
541     */
542    public String getName() {
543
544        return m_name;
545    }
546
547    /**
548     * Returns the "nice" display name of this module.<p>
549     *
550     * @return the "nice" display name of this module
551     */
552    public String getNiceName() {
553
554        return m_niceName;
555    }
556
557    /**
558     * Returns a parameter value from the module parameters.<p>
559     * 
560     * @param key the parameter to return the value for
561     * @return the parameter value from the module parameters
562     */
563    public String getParameter(String key) {
564
565        return m_parameters.get(key);
566    }
567
568    /**
569     * Returns a parameter value from the module parameters,
570     * or a given default value in case the parameter is not set.<p>
571     * 
572     * @param key the parameter to return the value for
573     * @param defaultValue the default value in case there is no value stored for this key
574     * @return the parameter value from the module parameters
575     */
576    public String getParameter(String key, String defaultValue) {
577
578        String value = m_parameters.get(key);
579        return (value != null) ? value : defaultValue;
580    }
581
582    /**
583     * Returns the configured (immutable) module parameters.<p>
584     * 
585     * @return the configured (immutable) module parameters
586     */
587    public SortedMap<String, String> getParameters() {
588
589        return m_parameters;
590    }
591
592    /**
593     * Returns the list of VFS resources that belong to this module.<p>
594     *
595     * @return the list of VFS resources that belong to this module
596     */
597    public List<String> getResources() {
598
599        return m_resources;
600    }
601
602    /**
603     * Returns the list of additional resource types that belong to this module.<p>
604     *
605     * @return the list of additional resource types that belong to this module
606     */
607    public List<I_CmsResourceType> getResourceTypes() {
608
609        return m_resourceTypes;
610    }
611
612    /**
613     * Returns the name of the user who uploaded this module.<p>
614     *
615     * @return the name of the user who uploaded this module
616     */
617    public String getUserInstalled() {
618
619        return m_userInstalled;
620    }
621
622    /**
623     * Returns the version of this module.<p>
624     *
625     * @return the version of this module
626     */
627    public CmsModuleVersion getVersion() {
628
629        return m_version;
630    }
631
632    /**
633     * @see java.lang.Object#hashCode()
634     */
635    @Override
636    public int hashCode() {
637
638        return m_name.hashCode();
639    }
640
641    /**
642     * Returns the createClassesFolder flag.<p>
643     *
644     * @return the createClassesFolder flag
645     */
646    public boolean isCreateClassesFolder() {
647
648        return m_createClassesFolder;
649    }
650
651    /**
652     * Returns the createElementsFolder flag.<p>
653     *
654     * @return the createElementsFolder flag
655     */
656    public boolean isCreateElementsFolder() {
657
658        return m_createElementsFolder;
659    }
660
661    /**
662     * Returns the createFormattersFolder flag.<p>
663     * 
664     * @return the createFormattersFolder flag 
665     */
666    public boolean isCreateFormattersFolder() {
667
668        return m_createFormattersFolder;
669    }
670
671    /**
672     * Returns the createLibFolder flag.<p>
673     *
674     * @return the createLibFolder flag
675     */
676    public boolean isCreateLibFolder() {
677
678        return m_createLibFolder;
679    }
680
681    /**
682     * Returns the createModuleFolder flag.<p>
683     *
684     * @return the createModuleFolder flag
685     */
686    public boolean isCreateModuleFolder() {
687
688        return m_createModuleFolder;
689    }
690
691    /**
692     * Returns the createResourcesFolder flag.<p>
693     *
694     * @return the createResourcesFolder flag
695     */
696    public boolean isCreateResourcesFolder() {
697
698        return m_createResourcesFolder;
699    }
700
701    /**
702     * Returns the createSchemasFolder flag.<p>
703     *
704     * @return the createSchemasFolder flag
705     */
706    public boolean isCreateSchemasFolder() {
707
708        return m_createSchemasFolder;
709    }
710
711    /**
712     * Returns the createTemplateFolder flag.<p>
713     *
714     * @return the createTemplateFolder flag
715     */
716    public boolean isCreateTemplateFolder() {
717
718        return m_createTemplateFolder;
719    }
720
721    /**
722     * Checks if this module is identical with another module.<p>
723     * 
724     * Modules A, B are <b>identical</b> if <i>all</i> values of A are equal to B.
725     * The values from {@link #getUserInstalled()} and {@link #getDateInstalled()} 
726     * are ignored for this test.<p>
727     *  
728     * Modules A, B are <b>equal</b> if just the name of A is equal to the name of B.<p>
729     * 
730     * @param other the module to compare with
731     * 
732     * @return if the modules are identical
733     * 
734     * @see #equals(Object)
735     */
736    public boolean isIdentical(CmsModule other) {
737
738        // some code redundancy here but this is easier to debug 
739        if (!isEqual(m_name, other.m_name)) {
740            return false;
741        }
742        if (!isEqual(m_niceName, other.m_niceName)) {
743            return false;
744        }
745        if (!isEqual(m_version, other.m_version)) {
746            return false;
747        }
748        if (!isEqual(m_actionClass, other.m_actionClass)) {
749            return false;
750        }
751        if (!isEqual(m_description, other.m_description)) {
752            return false;
753        }
754        if (!isEqual(m_authorName, other.m_authorName)) {
755            return false;
756        }
757        if (!isEqual(m_authorEmail, other.m_authorEmail)) {
758            return false;
759        }
760        if (m_dateCreated != other.m_dateCreated) {
761            return false;
762        }
763        return true;
764    }
765
766    /**
767     * Sets the class name of this modules (optional) action class.<p>
768     * 
769     * Providing <code>null</code> as a value indicates that this module does not use an action class.<p>
770     * 
771     * <i>Please note:</i>It's not possible to set the action class name once the module
772     * configuration has been frozen.<p> 
773     * 
774     * @param value the class name of this modules (optional) action class to set
775     */
776    public void setActionClass(String value) {
777
778        checkFrozen();
779        if (CmsStringUtil.isEmpty(value)) {
780            m_actionClass = null;
781        } else {
782            if (!CmsStringUtil.isValidJavaClassName(value)) {
783                throw new CmsIllegalArgumentException(Messages.get().container(
784                    Messages.ERR_MODULE_ACTION_CLASS_2,
785                    value,
786                    getName()));
787            }
788            m_actionClass = value;
789        }
790    }
791
792    /**
793     * Sets the author email of this module.<p>
794     * 
795     * 
796     * <i>Please note:</i>It's not possible to set the modules author email once the module
797     * configuration has been frozen.<p>
798     * 
799     * @param value the module description to set
800     */
801    public void setAuthorEmail(String value) {
802
803        checkFrozen();
804        m_authorEmail = value.trim();
805    }
806
807    /**
808     * Sets the author name of this module.<p>
809     * 
810     * 
811     * <i>Please note:</i>It's not possible to set the modules author name once the module
812     * configuration has been frozen.<p>
813     * 
814     * @param value the module description to set
815     */
816    public void setAuthorName(String value) {
817
818        checkFrozen();
819        m_authorName = value.trim();
820    }
821
822    /**
823     * Sets the createClassesFolder flag.<p>
824     *
825     * @param createClassesFolder the createClassesFolder flag to set
826     */
827    public void setCreateClassesFolder(boolean createClassesFolder) {
828
829        m_createClassesFolder = createClassesFolder;
830    }
831
832    /**
833     * Sets the createElementsFolder flag.<p>
834     *
835     * @param createElementsFolder the createElementsFolder flag to set
836     */
837    public void setCreateElementsFolder(boolean createElementsFolder) {
838
839        m_createElementsFolder = createElementsFolder;
840    }
841
842    /**
843     * Sets the createFormattersFolder flag.<p>
844     * 
845     * @param createFormattersFolder the createFormattersFolder flag to set
846     */
847    public void setCreateFormattersFolder(boolean createFormattersFolder) {
848
849        m_createFormattersFolder = createFormattersFolder;
850    }
851
852    /**
853     * Sets the createLibFolder flag.<p>
854     *
855     * @param createLibFolder the createLibFolder flag to set
856     */
857    public void setCreateLibFolder(boolean createLibFolder) {
858
859        m_createLibFolder = createLibFolder;
860    }
861
862    /**
863     * Sets the createModuleFolder flag.<p>
864     *
865     * @param createModuleFolder the createModuleFolder flag to set
866     */
867    public void setCreateModuleFolder(boolean createModuleFolder) {
868
869        m_createModuleFolder = createModuleFolder;
870    }
871
872    /**
873     * Sets the createResourcesFolder flag.<p>
874     *
875     * @param createResourcesFolder the createResourcesFolder flag to set
876     */
877    public void setCreateResourcesFolder(boolean createResourcesFolder) {
878
879        m_createResourcesFolder = createResourcesFolder;
880    }
881
882    /**
883     * Sets the createSchemasFolder flag .<p>
884     *
885     * @param createSchemasFolder the createSchemasFolder flag to set
886     */
887    public void setCreateSchemasFolder(boolean createSchemasFolder) {
888
889        m_createSchemasFolder = createSchemasFolder;
890    }
891
892    /**
893     * Sets the createTemplateFolder flag .<p>
894     *
895     * @param createTemplateFolder the createTemplateFolder flag to set
896     */
897    public void setCreateTemplateFolder(boolean createTemplateFolder) {
898
899        m_createTemplateFolder = createTemplateFolder;
900    }
901
902    /**
903     * Sets the date created of this module.<p>
904     * 
905     * 
906     * <i>Please note:</i>It's not possible to set the module date created once the module
907     * configuration has been frozen.<p>
908     * 
909     * @param value the date created to set
910     */
911    public void setDateCreated(long value) {
912
913        checkFrozen();
914        m_dateCreated = value;
915    }
916
917    /**
918     * Sets the installation date of this module.<p>
919     * 
920     * 
921     * <i>Please note:</i>It's not possible to set the installation date once the module
922     * configuration has been frozen.<p>
923     * 
924     * @param value the installation date this module
925     */
926    public void setDateInstalled(long value) {
927
928        checkFrozen();
929        m_dateInstalled = value;
930    }
931
932    /**
933     * Sets the list of module dependencies.<p>
934     *
935     * @param dependencies list of module dependencies
936     */
937    public void setDependencies(List<CmsModuleDependency> dependencies) {
938
939        checkFrozen();
940        m_dependencies = dependencies;
941    }
942
943    /**
944     * Sets the description of this module.<p>
945     * 
946     * 
947     * <i>Please note:</i>It's not possible to set the modules description once the module
948     * configuration has been frozen.<p>
949     * 
950     * @param value the module description to set
951     */
952    public void setDescription(String value) {
953
954        checkFrozen();
955        m_description = value.trim();
956    }
957
958    /**
959     * Sets the additional explorer types that belong to this module.<p>
960     *
961     * @param explorerTypeSettings the explorer type settings.
962     */
963    public void setExplorerTypes(List<CmsExplorerTypeSettings> explorerTypeSettings) {
964
965        m_explorerTypeSettings = explorerTypeSettings;
966    }
967
968    /**
969     * Sets the export points of this module.<p>
970     *
971     * @param exportPoints the export points of this module.
972     */
973    public void setExportPoints(List<CmsExportPoint> exportPoints) {
974
975        m_exportPoints = exportPoints;
976    }
977
978    /**
979     * Sets the group name of this module.<p>
980     * 
981     * 
982     * <i>Please note:</i>It's not possible to set the modules group name once the module
983     * configuration has been frozen.<p>
984     * 
985     * @param value the module group name to set
986     */
987    public void setGroup(String value) {
988
989        checkFrozen();
990        m_group = value;
991    }
992
993    /**
994     * Sets the name of this module.<p>
995     * 
996     * The module name must be a valid java package name.<p>
997     * 
998     * <i>Please note:</i>It's not possible to set the modules name once the module
999     * configuration has been frozen.<p>
1000     * 
1001     * @param value the module name to set
1002     */
1003    public void setName(String value) {
1004
1005        checkFrozen();
1006        if (!CmsStringUtil.isValidJavaClassName(value)) {
1007            throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_MODULE_NAME_1, value));
1008        }
1009        m_name = value;
1010    }
1011
1012    /**
1013     * Sets the "nice" display name of this module.<p>
1014     * 
1015     * <i>Please note:</i>It's not possible to set the modules "nice" name once the module
1016     * configuration has been frozen.<p> 
1017     * 
1018     * @param value the "nice" display name of this module to set
1019     */
1020    public void setNiceName(String value) {
1021
1022        checkFrozen();
1023        if (CmsStringUtil.isEmptyOrWhitespaceOnly(value)) {
1024            m_niceName = getName();
1025        } else {
1026            m_niceName = value.trim();
1027        }
1028    }
1029
1030    /**
1031     * Sets the parameters of this module.<p>
1032     * 
1033     * 
1034     * <i>Please note:</i>It's not possible to set the module parameters once the module
1035     * configuration has been frozen.<p>
1036     * 
1037     * @param parameters the module parameters to set
1038     */
1039    public void setParameters(SortedMap<String, String> parameters) {
1040
1041        checkFrozen();
1042        m_parameters = parameters;
1043    }
1044
1045    /**
1046     * Sets the resources of this module.<p>
1047     * 
1048     * 
1049     * <i>Please note:</i>It's not possible to set the module resources once the module
1050     * configuration has been frozen.<p>
1051     * 
1052     * @param value the module resources to set
1053     */
1054    public void setResources(List<String> value) {
1055
1056        checkFrozen();
1057        m_resources = value;
1058    }
1059
1060    /**
1061     * Sets the list of additional resource types that belong to this module.<p>
1062     *
1063     * @param resourceTypes list of additional resource types that belong to this module
1064     */
1065    public void setResourceTypes(List<I_CmsResourceType> resourceTypes) {
1066
1067        m_resourceTypes = Collections.unmodifiableList(resourceTypes);
1068    }
1069
1070    /**
1071     * Sets the user who installed of this module.<p>
1072     * 
1073     * 
1074     * <i>Please note:</i>It's not possible to set the user installed once the module
1075     * configuration has been frozen.<p>
1076     * 
1077     * @param value the user who installed this module
1078     */
1079    public void setUserInstalled(String value) {
1080
1081        checkFrozen();
1082        m_userInstalled = value.trim();
1083    }
1084
1085    /**
1086     * Checks if this modules configuration is frozen.<p>
1087     * 
1088     * @throws CmsIllegalArgumentException in case the configuration is already frozen
1089     */
1090    protected void checkFrozen() throws CmsIllegalArgumentException {
1091
1092        if (m_frozen) {
1093            throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_MODULE_FROZEN_1, getName()));
1094        }
1095    }
1096
1097    /**
1098     * Initializes this module, also freezing the module configuration.<p>
1099     * 
1100     * @param cms an initialized OpenCms user context
1101     * 
1102     * @throws CmsRoleViolationException if the given users does not have the <code>{@link CmsRole#DATABASE_MANAGER}</code> role 
1103     */
1104    protected void initialize(CmsObject cms) throws CmsRoleViolationException {
1105
1106        checkFrozen();
1107        // check if the user has the required permissions
1108        OpenCms.getRoleManager().checkRole(cms, CmsRole.DATABASE_MANAGER);
1109
1110        m_frozen = true;
1111        m_resources = Collections.unmodifiableList(m_resources);
1112    }
1113
1114    /**
1115     * Sets the module action instance for this module.<p>
1116     * 
1117     * @param actionInstance the module action instance for this module
1118     */
1119    /*package*/void setActionInstance(I_CmsModuleAction actionInstance) {
1120
1121        m_actionInstance = actionInstance;
1122
1123    }
1124
1125    /**
1126     * Resolves the module property "additionalresources" to the resource list and
1127     * vice versa.<p>
1128     * 
1129     * This "special" module property is required as long as we do not have a new 
1130     * GUI for editing of module resource entries. Once we have the new GUI, the 
1131     * handling of "additionalresources" will be moved to the import of the module 
1132     * and done only if the imported module is a 5.0 module.<p>
1133     */
1134    private void initOldAdditionalResources() {
1135
1136        SortedMap<String, String> parameters = new TreeMap<String, String>(m_parameters);
1137        List<String> resources = new ArrayList<String>(m_resources);
1138
1139        String additionalResources;
1140        additionalResources = parameters.get(MODULE_PROPERTY_ADDITIONAL_RESOURCES);
1141        if (additionalResources != null) {
1142            StringTokenizer tok = new StringTokenizer(
1143                additionalResources,
1144                MODULE_PROPERTY_ADDITIONAL_RESOURCES_SEPARATOR);
1145            while (tok.hasMoreTokens()) {
1146                String resource = tok.nextToken().trim();
1147                if ((!"-".equals(resource)) && (!resources.contains(resource))) {
1148                    resources.add(resource);
1149                }
1150            }
1151        }
1152
1153        m_resources = resources;
1154    }
1155
1156    /**
1157     * Checks if two objects are either both null, or equal.<p>
1158     * 
1159     * @param a the first object to check
1160     * @param b the second object to check 
1161     * @return true if the two object are either both null, or equal
1162     */
1163    private boolean isEqual(Object a, Object b) {
1164
1165        if (a == null) {
1166            return (b == null);
1167        }
1168        if (b == null) {
1169            return false;
1170        }
1171        return a.equals(b);
1172    }
1173}