001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (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 & Co. KG, 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.configuration.CmsVfsConfiguration;
031import org.opencms.configuration.CmsWorkplaceConfiguration;
032import org.opencms.configuration.I_CmsConfigurationParameterHandler;
033import org.opencms.configuration.I_CmsXmlConfiguration;
034import org.opencms.db.CmsExportPoint;
035import org.opencms.file.types.I_CmsResourceType;
036import org.opencms.main.CmsLog;
037import org.opencms.module.CmsModule.ExportMode;
038import org.opencms.util.CmsDateUtil;
039import org.opencms.util.CmsStringUtil;
040import org.opencms.workplace.CmsWorkplace;
041import org.opencms.workplace.explorer.CmsExplorerTypeSettings;
042
043import java.text.ParseException;
044import java.util.ArrayList;
045import java.util.Collections;
046import java.util.HashMap;
047import java.util.Iterator;
048import java.util.List;
049import java.util.Map;
050import java.util.SortedMap;
051
052import org.apache.commons.digester3.Digester;
053import org.apache.commons.digester3.Rule;
054import org.apache.commons.logging.Log;
055
056import org.dom4j.Document;
057import org.dom4j.DocumentHelper;
058import org.dom4j.Element;
059
060/**
061 * Adds the XML handler rules for import and export of a single module.<p>
062 *
063 * @since 6.0.0
064 */
065public class CmsModuleXmlHandler {
066
067    /**
068     * Enum used to distinguish whether we want to generate the XML for a module export's manifest or the XML for writing back
069     * opencms-modules.xml.
070     */
071    public enum XmlWriteMode {
072    /** Generating XML for the configuration. */
073    config,
074
075    /** Generating XML for a manifest. */
076    manifest
077    }
078
079    /** The "name" attribute. */
080    public static final String A_NAME = "name";
081
082    /** The "version" attribute. */
083    public static final String A_VERSION = "version";
084
085    /** The node name for the authoremail node. */
086    public static final String N_AUTHOREMAIL = "authoremail";
087
088    /** The node name for the authorname node. */
089    public static final String N_AUTHORNAME = "authorname";
090
091    /** The node name for the auto increment mode. */
092    public static final String N_AUTOINCREMENT = "autoincrement";
093
094    /** The node name for the checkpoint time. */
095    public static final String N_CHECKPOINT_TIME = "checkpoint-time";
096
097    /** The node name for the class node. */
098    public static final String N_CLASS = "class";
099
100    /** The node name for the datecreated node. */
101    public static final String N_DATECREATED = "datecreated";
102
103    /** The node name for the date installed node. */
104    public static final String N_DATEINSTALLED = "dateinstalled";
105
106    /** The node name for the dependencies node. */
107    public static final String N_DEPENDENCIES = "dependencies";
108
109    /** The node name for the dependency node. */
110    public static final String N_DEPENDENCY = "dependency";
111
112    /** The node name for the description node. */
113    public static final String N_DESCRIPTION = "description";
114
115    /** The node name for the resources node. */
116    public static final String N_EXCLUDERESOURCES = "excluderesources";
117
118    /** The node name for the import site. */
119    public static final String N_EXPORT_MODE = "export-mode";
120
121    /** The node name for the group node. */
122    public static final String N_GROUP = "group";
123
124    /** Node for the import script. */
125    public static final String N_IMPORT_SCRIPT = "import-script";
126
127    /** The node name for a module. */
128    public static final String N_MODULE = "module";
129
130    /** The node name for the name node. */
131    public static final String N_NAME = "name";
132
133    /** The node name for the nicename node. */
134    public static final String N_NICENAME = "nicename";
135
136    /** The "param" node name for generic parameters. */
137    public static final String N_PARAM = "param";
138
139    /** The node name for the parameters node. */
140    public static final String N_PARAMETERS = "parameters";
141
142    /** The node name for the resources node. */
143    public static final String N_RESOURCES = "resources";
144
145    /** The node name for the module site. */
146    public static final String N_SITE = "site";
147
148    /** The node name for the user installed node. */
149    public static final String N_USERINSTALLED = "userinstalled";
150
151    /** The node name for the version node. */
152    public static final String N_VERSION = "version";
153
154    /** The log object for this class. */
155    private static final Log LOG = CmsLog.getLog(CmsModuleXmlHandler.class);
156
157    /** The node name for the import site. */
158    private static final String N_IMPORT_SITE = "import-site";
159
160    /** The auto-increment value. */
161    private boolean m_autoIncrement;
162
163    /** The checkpoint time. */
164    private long m_checkpointTime;
165
166    /** The list of dependencies for a module. */
167    private List<CmsModuleDependency> m_dependencies;
168
169    /** The list of resources excluded for a module. */
170    private List<String> m_excluderesources;
171
172    /** The explorer type settings. */
173    private List<CmsExplorerTypeSettings> m_explorerTypeSettings;
174
175    /** The list of export points for a module. */
176    private List<CmsExportPoint> m_exportPoints;
177
178    /** The generated module. */
179    private CmsModule m_module;
180
181    /** Indicates if the module was an old (5.0.x) style module. */
182    private boolean m_oldModule;
183
184    /** The module parameters. */
185    private Map<String, String> m_parameters;
186
187    /** The list of resources for a module. */
188    private List<String> m_resources;
189
190    /** The list of additional resource types. */
191    private List<I_CmsResourceType> m_resourceTypes;
192
193    /**
194     * Public constructor, will be called by digester during import.<p>
195     */
196    public CmsModuleXmlHandler() {
197
198        m_exportPoints = new ArrayList<CmsExportPoint>();
199        m_dependencies = new ArrayList<CmsModuleDependency>();
200        m_resources = new ArrayList<String>();
201        m_excluderesources = new ArrayList<String>();
202        m_parameters = new HashMap<String, String>();
203        m_resourceTypes = new ArrayList<I_CmsResourceType>();
204        m_explorerTypeSettings = new ArrayList<CmsExplorerTypeSettings>();
205    }
206
207    /**
208     * Adds the XML digester rules for a single module.<p>
209     *
210     * @param digester the digester to add the rules to
211     */
212    public static void addXmlDigesterRules(Digester digester) {
213
214        // add class generation rule
215        digester.addObjectCreate("*/" + N_MODULE, CmsModuleXmlHandler.class);
216        digester.addSetNext("*/" + N_MODULE, "setModule");
217
218        // add rules for base module information
219
220        // NOTE: If you change the order of parameters here or add new ones, you may
221        // also need to change the corresponding parameter indexes in the method addXmlDigesterRulesForVersion5Modules.
222        digester.addCallMethod("*/" + N_MODULE, "createdModule", 15);
223        digester.addCallParam("*/" + N_MODULE + "/" + N_NAME, 0);
224        digester.addCallParam("*/" + N_MODULE + "/" + N_NICENAME, 1);
225        digester.addCallParam("*/" + N_MODULE + "/" + N_GROUP, 2);
226        digester.addCallParam("*/" + N_MODULE + "/" + N_CLASS, 3);
227        digester.addCallParam("*/" + N_MODULE + "/" + N_IMPORT_SCRIPT, 4);
228        digester.addCallParam("*/" + N_MODULE + "/" + N_IMPORT_SITE, 5);
229        digester.addCallParam("*/" + N_MODULE + "/" + N_SITE, 6);
230        digester.addCallParam("*/" + N_MODULE + "/" + N_EXPORT_MODE, 7, I_CmsXmlConfiguration.A_NAME);
231        digester.addCallParam("*/" + N_MODULE + "/" + N_DESCRIPTION, 8);
232        digester.addCallParam("*/" + N_MODULE + "/" + N_VERSION, 9);
233        digester.addCallParam("*/" + N_MODULE + "/" + N_AUTHORNAME, 10);
234        digester.addCallParam("*/" + N_MODULE + "/" + N_AUTHOREMAIL, 11);
235        digester.addCallParam("*/" + N_MODULE + "/" + N_DATECREATED, 12);
236        digester.addCallParam("*/" + N_MODULE + "/" + N_USERINSTALLED, 13);
237        digester.addCallParam("*/" + N_MODULE + "/" + N_DATEINSTALLED, 14);
238
239        digester.addRule("*/" + N_MODULE + "/" + N_AUTOINCREMENT, new Rule() {
240
241            @Override
242            public void body(String namespace, String name, String text) throws Exception {
243
244                CmsModuleXmlHandler handler = (CmsModuleXmlHandler)(getDigester().peek());
245                handler.setAutoIncrement(Boolean.parseBoolean(text.trim()));
246            }
247        });
248
249        digester.addRule("*/" + N_MODULE + "/" + N_CHECKPOINT_TIME, new Rule() {
250
251            @Override
252            public void body(String namespace, String name, String text) throws Exception {
253
254                CmsModuleXmlHandler handler = (CmsModuleXmlHandler)(getDigester().peek());
255                handler.setCheckpointTime(Long.parseLong(text.trim()));
256            }
257        });
258
259        // add rules for module dependencies
260        digester.addCallMethod("*/" + N_MODULE + "/" + N_DEPENDENCIES + "/" + N_DEPENDENCY, "addDependency", 2);
261        digester.addCallParam(
262            "*/" + N_MODULE + "/" + N_DEPENDENCIES + "/" + N_DEPENDENCY,
263            0,
264            I_CmsXmlConfiguration.A_NAME);
265        digester.addCallParam("*/" + N_MODULE + "/" + N_DEPENDENCIES + "/" + N_DEPENDENCY, 1, A_VERSION);
266
267        // add rules for the module export points
268        digester.addCallMethod(
269            "*/" + N_MODULE + "/" + I_CmsXmlConfiguration.N_EXPORTPOINTS + "/" + I_CmsXmlConfiguration.N_EXPORTPOINT,
270            "addExportPoint",
271            2);
272        digester.addCallParam(
273            "*/" + N_MODULE + "/" + I_CmsXmlConfiguration.N_EXPORTPOINTS + "/" + I_CmsXmlConfiguration.N_EXPORTPOINT,
274            0,
275            I_CmsXmlConfiguration.A_URI);
276        digester.addCallParam(
277            "*/" + N_MODULE + "/" + I_CmsXmlConfiguration.N_EXPORTPOINTS + "/" + I_CmsXmlConfiguration.N_EXPORTPOINT,
278            1,
279            I_CmsXmlConfiguration.A_DESTINATION);
280
281        // add rules for the module resources
282        digester.addCallMethod(
283            "*/" + N_MODULE + "/" + N_RESOURCES + "/" + I_CmsXmlConfiguration.N_RESOURCE,
284            "addResource",
285            1);
286        digester.addCallParam(
287            "*/" + N_MODULE + "/" + N_RESOURCES + "/" + I_CmsXmlConfiguration.N_RESOURCE,
288            0,
289            I_CmsXmlConfiguration.A_URI);
290
291        // add rules for the module exclude resources
292        digester.addCallMethod(
293            "*/" + N_MODULE + "/" + N_EXCLUDERESOURCES + "/" + I_CmsXmlConfiguration.N_RESOURCE,
294            "addExcludeResource",
295            1);
296        digester.addCallParam(
297            "*/" + N_MODULE + "/" + N_EXCLUDERESOURCES + "/" + I_CmsXmlConfiguration.N_RESOURCE,
298            0,
299            I_CmsXmlConfiguration.A_URI);
300
301        // add rules for the module parameters
302        digester.addCallMethod(
303            "*/" + N_MODULE + "/" + N_PARAMETERS + "/" + I_CmsXmlConfiguration.N_PARAM,
304            "addParameter",
305            2);
306        digester.addCallParam(
307            "*/" + N_MODULE + "/" + N_PARAMETERS + "/" + I_CmsXmlConfiguration.N_PARAM,
308            0,
309            I_CmsXmlConfiguration.A_NAME);
310        digester.addCallParam("*/" + N_MODULE + "/" + N_PARAMETERS + "/" + I_CmsXmlConfiguration.N_PARAM, 1);
311
312        // generic <param> parameter rules
313        digester.addCallMethod(
314            "*/" + I_CmsXmlConfiguration.N_PARAM,
315            I_CmsConfigurationParameterHandler.ADD_PARAMETER_METHOD,
316            2);
317        digester.addCallParam("*/" + I_CmsXmlConfiguration.N_PARAM, 0, I_CmsXmlConfiguration.A_NAME);
318        digester.addCallParam("*/" + I_CmsXmlConfiguration.N_PARAM, 1);
319
320        // add resource type rules from VFS
321        CmsVfsConfiguration.addResourceTypeXmlRules(digester);
322
323        // add explorer type rules from workplace
324        CmsWorkplaceConfiguration.addExplorerTypeXmlRules(digester);
325
326        // finally add all rules for backward compatibility with OpenCms 5.0
327        addXmlDigesterRulesForVersion5Modules(digester);
328    }
329
330    /**
331     * Generates a detached XML element for a module.<p>
332     *
333     * @param module the module to generate the XML element for
334     * @param writeMode enum value representing the context for which we are generating the XML
335     *
336     * @return the detached XML element for the module
337     */
338    public static Element generateXml(CmsModule module, XmlWriteMode writeMode) {
339
340        Document doc = DocumentHelper.createDocument();
341
342        Element moduleElement = doc.addElement(N_MODULE);
343
344        moduleElement.addElement(N_NAME).setText(module.getName());
345        if (!module.getName().equals(module.getNiceName())) {
346            moduleElement.addElement(N_NICENAME).addCDATA(module.getNiceName());
347        } else {
348            moduleElement.addElement(N_NICENAME);
349        }
350        if (CmsStringUtil.isNotEmpty(module.getGroup())) {
351            moduleElement.addElement(N_GROUP).setText(module.getGroup());
352        }
353        if (CmsStringUtil.isNotEmpty(module.getActionClass())) {
354            moduleElement.addElement(N_CLASS).setText(module.getActionClass());
355        } else {
356            moduleElement.addElement(N_CLASS);
357        }
358
359        String importScript = module.getImportScript();
360        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(importScript)) {
361            moduleElement.addElement(N_IMPORT_SCRIPT).addCDATA(importScript);
362        }
363
364        String site = module.getSite();
365        boolean isImportSite = module.hasImportSite();
366
367        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(site)) {
368            moduleElement.addElement(isImportSite ? N_IMPORT_SITE : N_SITE).setText(site);
369        }
370
371        moduleElement.addElement(N_EXPORT_MODE).addAttribute(A_NAME, module.getExportMode().toString());
372
373        if (CmsStringUtil.isNotEmpty(module.getDescription())) {
374            moduleElement.addElement(N_DESCRIPTION).addCDATA(module.getDescription());
375        } else {
376            moduleElement.addElement(N_DESCRIPTION);
377        }
378        moduleElement.addElement(N_VERSION).setText(module.getVersion().toString());
379        if (module.isAutoIncrement()) {
380            moduleElement.addElement(N_AUTOINCREMENT).setText(Boolean.TRUE.toString());
381        }
382        if ((module.getCheckpointTime() != 0) && (writeMode == XmlWriteMode.config)) {
383            moduleElement.addElement(N_CHECKPOINT_TIME).setText("" + module.getCheckpointTime());
384        }
385
386        if (CmsStringUtil.isNotEmpty(module.getAuthorName())) {
387            moduleElement.addElement(N_AUTHORNAME).addCDATA(module.getAuthorName());
388        } else {
389            moduleElement.addElement(N_AUTHORNAME);
390        }
391        if (CmsStringUtil.isNotEmpty(module.getAuthorEmail())) {
392            moduleElement.addElement(N_AUTHOREMAIL).addCDATA(module.getAuthorEmail());
393        } else {
394            moduleElement.addElement(N_AUTHOREMAIL);
395        }
396        if (module.getDateCreated() != CmsModule.DEFAULT_DATE) {
397            moduleElement.addElement(N_DATECREATED).setText(CmsDateUtil.getHeaderDate(module.getDateCreated()));
398        } else {
399            moduleElement.addElement(N_DATECREATED);
400        }
401
402        if (!module.isReducedExportMode() && CmsStringUtil.isNotEmpty(module.getUserInstalled())) {
403            moduleElement.addElement(N_USERINSTALLED).setText(module.getUserInstalled());
404        } else {
405            moduleElement.addElement(N_USERINSTALLED);
406        }
407        if (!module.isReducedExportMode() && (module.getDateInstalled() != CmsModule.DEFAULT_DATE)) {
408            moduleElement.addElement(N_DATEINSTALLED).setText(CmsDateUtil.getHeaderDate(module.getDateInstalled()));
409        } else {
410            moduleElement.addElement(N_DATEINSTALLED);
411        }
412        Element dependenciesElement = moduleElement.addElement(N_DEPENDENCIES);
413        for (int i = 0; i < module.getDependencies().size(); i++) {
414            CmsModuleDependency dependency = module.getDependencies().get(i);
415            dependenciesElement.addElement(N_DEPENDENCY).addAttribute(
416                I_CmsXmlConfiguration.A_NAME,
417                dependency.getName()).addAttribute(A_VERSION, dependency.getVersion().toString());
418        }
419        Element exportpointsElement = moduleElement.addElement(I_CmsXmlConfiguration.N_EXPORTPOINTS);
420        for (int i = 0; i < module.getExportPoints().size(); i++) {
421            CmsExportPoint point = module.getExportPoints().get(i);
422            exportpointsElement.addElement(I_CmsXmlConfiguration.N_EXPORTPOINT).addAttribute(
423                I_CmsXmlConfiguration.A_URI,
424                point.getUri()).addAttribute(I_CmsXmlConfiguration.A_DESTINATION, point.getConfiguredDestination());
425        }
426        Element resourcesElement = moduleElement.addElement(N_RESOURCES);
427        for (int i = 0; i < module.getResources().size(); i++) {
428            String resource = module.getResources().get(i);
429            resourcesElement.addElement(I_CmsXmlConfiguration.N_RESOURCE).addAttribute(
430                I_CmsXmlConfiguration.A_URI,
431                resource);
432        }
433        Element excludeResourcesElement = moduleElement.addElement(N_EXCLUDERESOURCES);
434        for (String resource : module.getExcludeResources()) {
435            excludeResourcesElement.addElement(I_CmsXmlConfiguration.N_RESOURCE).addAttribute(
436                I_CmsXmlConfiguration.A_URI,
437                resource);
438        }
439        Element parametersElement = moduleElement.addElement(N_PARAMETERS);
440        SortedMap<String, String> parameters = module.getParameters();
441        if (parameters != null) {
442            List<String> names = new ArrayList<String>(parameters.keySet());
443            Collections.sort(names);
444            for (String name : names) {
445                String value = parameters.get(name).toString();
446                Element paramNode = parametersElement.addElement(I_CmsXmlConfiguration.N_PARAM);
447                paramNode.addAttribute(I_CmsXmlConfiguration.A_NAME, name);
448                paramNode.addText(value);
449            }
450        }
451
452        // add resource types
453        List<I_CmsResourceType> resourceTypes = module.getResourceTypes();
454        if (resourceTypes.size() > 0) {
455            Element resourcetypesElement = moduleElement.addElement(CmsVfsConfiguration.N_RESOURCETYPES);
456            CmsVfsConfiguration.generateResourceTypeXml(resourcetypesElement, resourceTypes, true);
457        }
458
459        List<CmsExplorerTypeSettings> explorerTypes = module.getExplorerTypes();
460        if (explorerTypes.size() > 0) {
461            Element explorerTypesElement = moduleElement.addElement(CmsWorkplaceConfiguration.N_EXPLORERTYPES);
462            CmsWorkplaceConfiguration.generateExplorerTypesXml(explorerTypesElement, explorerTypes, true);
463        }
464
465        // return the modules node
466        moduleElement.detach();
467        return moduleElement;
468    }
469
470    /**
471     * Generates a (hopefully) valid Java class name from an invalid class name.<p>
472     *
473     * All invalid characters are replaced by an underscore "_".
474     * This is for example used to make sure old (5.0) modules can still be imported,
475     * by converting the name to a valid class name.<p>
476     *
477     * @param className the class name to make valid
478     *
479     * @return a valid Java class name from an invalid class name
480     */
481    public static String makeValidJavaClassName(String className) {
482
483        StringBuffer result = new StringBuffer(className.length());
484        int length = className.length();
485        boolean nodot = true;
486        for (int i = 0; i < length; i++) {
487            char ch = className.charAt(i);
488            if (nodot) {
489                if (ch == '.') {
490                    // ignore, remove
491                } else if (Character.isJavaIdentifierStart(ch)) {
492                    nodot = false;
493                    result.append(ch);
494                } else {
495                    result.append('_');
496                }
497            } else {
498                if (ch == '.') {
499                    nodot = true;
500                    result.append(ch);
501                } else if (Character.isJavaIdentifierPart(ch)) {
502                    nodot = false;
503                    result.append(ch);
504                } else {
505                    result.append('_');
506                }
507            }
508        }
509        return result.toString();
510    }
511
512    /**
513     * Adds the digester rules for OpenCms version 5 modules.<p>
514     *
515     * @param digester the digester to add the rules to
516     */
517    private static void addXmlDigesterRulesForVersion5Modules(Digester digester) {
518
519        // mark method
520        digester.addCallMethod("*/" + N_MODULE + "/author", "setOldModule");
521
522        // base module information
523        digester.addCallParam("*/" + N_MODULE + "/author", 10);
524        digester.addCallParam("*/" + N_MODULE + "/email", 11);
525        digester.addCallParam("*/" + N_MODULE + "/creationdate", 12);
526
527        // dependencies
528        digester.addCallParam("*/" + N_MODULE + "/dependencies/dependency/name", 0);
529        digester.addCallParam("*/" + N_MODULE + "/dependencies/dependency/minversion", 1);
530
531        // export points
532        digester.addCallMethod("*/" + N_MODULE + "/exportpoint", "addExportPoint", 2);
533        digester.addCallParam("*/" + N_MODULE + "/exportpoint/source", 0);
534        digester.addCallParam("*/" + N_MODULE + "/exportpoint/destination", 1);
535
536        // parameters
537        digester.addCallMethod("*/" + N_MODULE + "/parameters/para", "addParameter", 2);
538        digester.addCallParam("*/" + N_MODULE + "/parameters/para/name", 0);
539        digester.addCallParam("*/" + N_MODULE + "/parameters/para/value", 1);
540    }
541
542    /**
543     * Adds a module dependency to the current module.<p>
544     *
545     * @param name the module name of the dependency
546     * @param version the module version of the dependency
547     */
548    public void addDependency(String name, String version) {
549
550        CmsModuleVersion moduleVersion = new CmsModuleVersion(version);
551
552        CmsModuleDependency dependency = new CmsModuleDependency(name, moduleVersion);
553        m_dependencies.add(dependency);
554
555        if (LOG.isDebugEnabled()) {
556            LOG.debug(Messages.get().getBundle().key(Messages.LOG_ADD_MOD_DEPENDENCY_2, name, version));
557        }
558    }
559
560    /**
561     * Adds a resource to the list module resources.<p>
562     *
563     * @param resource a resources uri in the OpenCms VFS
564     */
565    public void addExcludeResource(String resource) {
566
567        if (LOG.isDebugEnabled()) {
568            LOG.debug(Messages.get().getBundle().key(Messages.LOG_ADD_MOD_EXCLUDERESOURCE_1, resource));
569        }
570        m_excluderesources.add(resource);
571    }
572
573    /**
574     * Adds an explorer type setting object to the list of type settings.<p>
575     *
576     * Adds the type setting as well to a map with the resource type name as key.
577     *
578     * @param settings the explorer type settings
579     */
580    public void addExplorerTypeSetting(CmsExplorerTypeSettings settings) {
581
582        settings.setAddititionalModuleExplorerType(true);
583        m_explorerTypeSettings.add(settings);
584    }
585
586    /**
587     * Adds an export point to the module configuration.<p>
588     *
589     * @param uri the export point uri
590     * @param destination the export point destination
591     */
592    public void addExportPoint(String uri, String destination) {
593
594        CmsExportPoint point = new CmsExportPoint(uri, destination);
595        m_exportPoints.add(point);
596        if (CmsLog.INIT.isInfoEnabled()) {
597            CmsLog.INIT.info(
598                Messages.get().getBundle().key(
599                    Messages.INIT_ADD_EXPORT_POINT_2,
600                    point.getUri(),
601                    point.getConfiguredDestination()));
602        }
603    }
604
605    /**
606     * Adds a module parameter to the module configuration.<p>
607     *
608     * @param key the parameter key
609     * @param value the parameter value
610     */
611    public void addParameter(String key, String value) {
612
613        if (CmsStringUtil.isNotEmpty(key)) {
614            key = key.trim();
615        }
616        if (CmsStringUtil.isNotEmpty(value)) {
617            value = value.trim();
618        }
619        m_parameters.put(key, value);
620        if (LOG.isDebugEnabled()) {
621            LOG.debug(Messages.get().getBundle().key(Messages.LOG_ADD_MOD_PARAM_KEY_2, key, value));
622        }
623    }
624
625    /**
626     * Adds a resource to the list module resources.<p>
627     *
628     * @param resource a resources uri in the OpenCms VFS
629     */
630    public void addResource(String resource) {
631
632        if (LOG.isDebugEnabled()) {
633            LOG.debug(Messages.get().getBundle().key(Messages.LOG_ADD_MOD_RESOURCE_1, resource));
634        }
635        m_resources.add(resource);
636    }
637
638    /**
639     * Adds a new resource type to the internal list of loaded resource types.<p>
640     *
641     * @param resourceType the resource type to add
642     *
643     * @see I_CmsResourceType#ADD_RESOURCE_TYPE_METHOD
644     */
645    public void addResourceType(I_CmsResourceType resourceType) {
646
647        resourceType.setAdditionalModuleResourceType(true);
648        m_resourceTypes.add(resourceType);
649    }
650
651    /**
652     * Created a new module from the provided parameters.<p>
653     *
654     * @param name the name of this module, usually looks like a java package name
655     * @param niceName the "nice" display name of this module
656     * @param group the group of the module
657     * @param actionClass the (optional) module action class name
658     * @param importScript the import script
659     * @param importSite the import site (only one of importSite and site is not null)
660     * @param site the module site
661     * @param exportModeName the export mode name
662     * @param description the description of this module
663     * @param version the version of this module
664     * @param authorName the name of the author of this module
665     * @param authorEmail the email of the module author
666     * @param dateCreated the date this module was created by the author
667     * @param userInstalled the name of the user who uploaded this module
668     * @param dateInstalled the date this module was uploaded
669     */
670    public void createdModule(
671        String name,
672        String niceName,
673        String group,
674        String actionClass,
675        String importScript,
676        String importSite,
677        String site,
678        String exportModeName,
679        String description,
680        String version,
681        String authorName,
682        String authorEmail,
683        String dateCreated,
684        String userInstalled,
685        String dateInstalled) {
686
687        String moduleName;
688
689        if (!CmsStringUtil.isValidJavaClassName(name)) {
690            // ensure backward compatibility with old (5.0) module names
691            LOG.error(Messages.get().getBundle().key(Messages.LOG_INVALID_MOD_NAME_IMPORTED_1, name));
692            moduleName = makeValidJavaClassName(name);
693            LOG.error(Messages.get().getBundle().key(Messages.LOG_CORRECTED_MOD_NAME_1, moduleName));
694        } else {
695            moduleName = name;
696        }
697
698        // parse the module version
699        CmsModuleVersion moduleVersion = new CmsModuleVersion(version);
700
701        // parse date created
702        long moduleDateCreated = CmsModule.DEFAULT_DATE;
703        if (dateCreated != null) {
704            try {
705                moduleDateCreated = CmsDateUtil.parseHeaderDate(dateCreated);
706            } catch (ParseException e) {
707                // noop
708            }
709        }
710
711        // parse date installed
712        long moduleDateInstalled = CmsModule.DEFAULT_DATE;
713        if (dateInstalled != null) {
714            try {
715                moduleDateInstalled = CmsDateUtil.parseHeaderDate(dateInstalled);
716            } catch (ParseException e1) {
717                // noop
718            }
719        }
720
721        if (m_oldModule) {
722            // make sure module path is added to resources for "old" (5.0.x) modules
723            String modulePath = CmsWorkplace.VFS_PATH_MODULES + name + "/";
724            m_resources.add(modulePath);
725        }
726
727        ExportMode exportMode = ExportMode.DEFAULT;
728        try {
729            if (!CmsStringUtil.isEmptyOrWhitespaceOnly(exportModeName)) {
730                exportMode = ExportMode.valueOf(exportModeName.toUpperCase());
731            }
732        } catch (IllegalArgumentException e) {
733            LOG.warn(e.getLocalizedMessage(), e);
734            //stay with default export mode
735        }
736
737        String siteForConstructor;
738        boolean isImportSite;
739
740        if (importSite != null) {
741            siteForConstructor = importSite;
742            isImportSite = true;
743        } else {
744            siteForConstructor = site;
745            isImportSite = false;
746        }
747
748        // now create the module
749        m_module = new CmsModule(
750            moduleName,
751            niceName,
752            group,
753            actionClass,
754            importScript,
755            siteForConstructor,
756            isImportSite,
757            exportMode,
758            description,
759            moduleVersion,
760            authorName,
761            authorEmail,
762            moduleDateCreated,
763            userInstalled,
764            moduleDateInstalled,
765            m_dependencies,
766            m_exportPoints,
767            m_resources,
768            m_excluderesources,
769            m_parameters);
770
771        // store module name in the additional resource types
772        List<I_CmsResourceType> moduleResourceTypes = new ArrayList<I_CmsResourceType>(m_resourceTypes.size());
773        for (Iterator<I_CmsResourceType> i = m_resourceTypes.iterator(); i.hasNext();) {
774            I_CmsResourceType resType = i.next();
775            resType.setModuleName(moduleName);
776            moduleResourceTypes.add(resType);
777        }
778        // set the additional resource types;
779        m_module.setResourceTypes(moduleResourceTypes);
780
781        // set the additional explorer types
782        m_module.setExplorerTypes(m_explorerTypeSettings);
783
784        m_module.setAutoIncrement(m_autoIncrement);
785
786        m_module.setCheckpointTime(m_checkpointTime);
787    }
788
789    /**
790     * Returns the generated module.<p>
791     *
792     * @return the generated module
793     */
794    public CmsModule getModule() {
795
796        return m_module;
797    }
798
799    /**
800     * Sets the auto-increment mode.<p>
801     *
802     * @param autoincrement true if version auto-incrementation should be enabled
803     */
804    public void setAutoIncrement(boolean autoincrement) {
805
806        m_autoIncrement = autoincrement;
807    }
808
809    /**
810     * Sets the checkpoint time.<p>
811     *
812     * @param time the checkpoint time
813     */
814    public void setCheckpointTime(long time) {
815
816        m_checkpointTime = time;
817    }
818
819    /**
820     * Sets the current imported module to an old (5.0.x) style module.
821     */
822    public void setOldModule() {
823
824        m_oldModule = true;
825        if (LOG.isDebugEnabled()) {
826            LOG.debug(Messages.get().getBundle().key(Messages.LOG_OLD_MODULE_IMPORTED_0));
827        }
828    }
829}