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.configuration;
029
030import org.opencms.file.CmsProperty;
031import org.opencms.file.collectors.I_CmsResourceCollector;
032import org.opencms.file.types.CmsResourceTypeXmlContainerPage;
033import org.opencms.file.types.CmsResourceTypeXmlContent;
034import org.opencms.file.types.I_CmsResourceType;
035import org.opencms.loader.CmsDefaultFileNameGenerator;
036import org.opencms.loader.CmsMimeType;
037import org.opencms.loader.CmsResourceManager;
038import org.opencms.loader.I_CmsResourceLoader;
039import org.opencms.main.CmsLog;
040import org.opencms.main.OpenCms;
041import org.opencms.relations.CmsRelationType;
042import org.opencms.util.CmsHtmlConverterOption;
043import org.opencms.util.CmsResourceTranslator;
044import org.opencms.util.CmsStringUtil;
045import org.opencms.widgets.I_CmsWidget;
046import org.opencms.xml.CmsXmlContentTypeManager;
047import org.opencms.xml.types.I_CmsXmlSchemaType;
048
049import java.util.ArrayList;
050import java.util.Collections;
051import java.util.Iterator;
052import java.util.List;
053
054import org.apache.commons.digester.Digester;
055
056import org.dom4j.Element;
057
058/**
059 * VFS master configuration class.<p>
060 *
061 * @since 6.0.0
062 */
063public class CmsVfsConfiguration extends A_CmsXmlConfiguration {
064
065    /** The adjust-links-folder attribute. */
066    public static final String A_ADJUST_LINKS_FOLDER = "adjust-links-folder";
067
068    /** The widget configuration attribute. */
069    public static final String A_CONFIGURATION = "configuration";
070
071    /** The widget attribute. */
072    public static final String A_DEFAULTWIDGET = "defaultwidget";
073
074    /** The extension attribute name. */
075    public static final String A_EXTENSION = "extension";
076
077    /** The source attribute name. */
078    public static final String A_SOURCE = "source";
079
080    /** The target attribute name. */
081    public static final String A_TARGET = "target";
082
083    /** The name of the DTD for this configuration. */
084    public static final String CONFIGURATION_DTD_NAME = "opencms-vfs.dtd";
085
086    /** The name of the default XML file for this configuration. */
087    public static final String DEFAULT_XML_FILE_NAME = "opencms-vfs.xml";
088
089    /** The collector node name. */
090    public static final String N_COLLECTOR = "collector";
091
092    /** The collectors node name. */
093    public static final String N_COLLECTORS = "collectors";
094
095    /** The copy-resource node name.*/
096    public static final String N_COPY_RESOURCE = "copy-resource";
097
098    /** The copy-resources node name.*/
099    public static final String N_COPY_RESOURCES = "copy-resources";
100
101    /** The defaultfile node name. */
102    public static final String N_DEFAULTFILE = "defaultfile";
103
104    /** The defaultfiles node name. */
105    public static final String N_DEFAULTFILES = "defaultfiles";
106
107    /** File translations node name. */
108    public static final String N_FILETRANSLATIONS = "filetranslations";
109
110    /** Folder translations node name. */
111    public static final String N_FOLDERTRANSLATIONS = "foldertranslations";
112
113    /** The html-converter node name.*/
114    public static final String N_HTML_CONVERTER = "html-converter";
115
116    /** The html-converters node name.*/
117    public static final String N_HTML_CONVERTERS = "html-converters";
118
119    /** The node name of an individual resource loader. */
120    public static final String N_LOADER = "loader";
121
122    /** The mapping node name. */
123    public static final String N_MAPPING = "mapping";
124
125    /** The mappings node name. */
126    public static final String N_MAPPINGS = "mappings";
127
128    /** The mimetype node name. */
129    public static final String N_MIMETYPE = "mimetype";
130
131    /** The mimetypes node name. */
132    public static final String N_MIMETYPES = "mimetypes";
133
134    /** The properties node name. */
135    public static final String N_PROPERTIES = "properties";
136
137    /** The relation type node name. */
138    public static final String N_RELATIONTYPE = "relationtype";
139
140    /** The relation types node name. */
141    public static final String N_RELATIONTYPES = "relationtypes";
142
143    /** The resource loaders node name. */
144    public static final String N_RESOURCELOADERS = "resourceloaders";
145
146    /** The main resource node name. */
147    public static final String N_RESOURCES = "resources";
148
149    /** The resource types node name. */
150    public static final String N_RESOURCETYPES = "resourcetypes";
151
152    /** The schematype node name. */
153    public static final String N_SCHEMATYPE = "schematype";
154
155    /** The schematypes node name. */
156    public static final String N_SCHEMATYPES = "schematypes";
157
158    /** Individual translation node name. */
159    public static final String N_TRANSLATION = "translation";
160
161    /** The translations master node name. */
162    public static final String N_TRANSLATIONS = "translations";
163
164    /** The node name of an individual resource type. */
165    public static final String N_TYPE = "type";
166
167    /** The node name for the version history. */
168    public static final String N_VERSIONHISTORY = "versionhistory";
169
170    /** The main vfs configuration node name. */
171    public static final String N_VFS = "vfs";
172
173    /** The widget node name. */
174    public static final String N_WIDGET = "widget";
175
176    /** The widgets node name. */
177    public static final String N_WIDGETS = "widgets";
178
179    /** The xmlcontent node name. */
180    public static final String N_XMLCONTENT = "xmlcontent";
181
182    /** The xmlcontents node name. */
183    public static final String N_XMLCONTENTS = "xmlcontents";
184
185    /** XSD translations node name. */
186    public static final String N_XSDTRANSLATIONS = "xsdtranslations";
187
188    /** The namegenerator node name. */
189    private static final String N_NAMEGENERATOR = "namegenerator";
190
191    /** The configured XML content type manager. */
192    CmsXmlContentTypeManager m_xmlContentTypeManager;
193
194    /** The list of configured default files. */
195    private List<String> m_defaultFiles;
196
197    /** Controls if file translation is enabled. */
198    private boolean m_fileTranslationEnabled;
199
200    /** The list of file translations. */
201    private List<String> m_fileTranslations;
202
203    /** Controls if folder translation is enabled. */
204    private boolean m_folderTranslationEnabled;
205
206    /** The list of folder translations. */
207    private List<String> m_folderTranslations;
208
209    /** The configured resource manager. */
210    private CmsResourceManager m_resourceManager;
211
212    /** Controls if XSD translation is enabled. */
213    private boolean m_xsdTranslationEnabled;
214
215    /** The list of XSD translations. */
216    private List<String> m_xsdTranslations;
217
218    /**
219     * Adds the resource type rules to the given digester.<p>
220     *
221     * @param digester the digester to add the rules to
222     */
223    public static void addResourceTypeXmlRules(Digester digester) {
224
225        // add rules for resource types
226        digester.addFactoryCreate("*/" + N_RESOURCETYPES + "/" + N_TYPE, CmsDigesterResourceTypeCreationFactory.class);
227        digester.addSetNext("*/" + N_RESOURCETYPES + "/" + N_TYPE, I_CmsResourceType.ADD_RESOURCE_TYPE_METHOD);
228
229        // please note: the order of the rules is very important here,
230        // the "set next" rule (above) must be added _before_ the "call method" rule (below)!
231        // reason is digester will call the rule that was last added first
232        // here we must make sure that the resource type is initialized first (with the "call method" rule)
233        // before it is actually added to the resource type container (with the "set next" rule)
234        // otherwise there will be an empty resource type added to the container, and validation will not work
235        digester.addCallMethod(
236            "*/" + N_RESOURCETYPES + "/" + N_TYPE,
237            I_CmsConfigurationParameterHandler.INIT_CONFIGURATION_METHOD,
238            3);
239        // please note: the resource types use a special version of the init method with 3 parameters
240        digester.addCallParam("*/" + N_RESOURCETYPES + "/" + N_TYPE, 0, A_NAME);
241        digester.addCallParam("*/" + N_RESOURCETYPES + "/" + N_TYPE, 1, A_ID);
242        digester.addCallParam("*/" + N_RESOURCETYPES + "/" + N_TYPE, 2, A_CLASS);
243
244        // add rules for default properties
245        digester.addObjectCreate(
246            "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY,
247            CmsProperty.class);
248        digester.addCallMethod(
249            "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY + "/" + N_NAME,
250            "setName",
251            1);
252        digester.addCallParam(
253            "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY + "/" + N_NAME,
254            0);
255
256        digester.addCallMethod(
257            "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY + "/" + N_VALUE,
258            "setValue",
259            2);
260        digester.addCallParam(
261            "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY + "/" + N_VALUE,
262            0);
263        digester.addCallParam(
264            "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY + "/" + N_VALUE,
265            1,
266            A_TYPE);
267
268        digester.addSetNext(
269            "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_PROPERTIES + "/" + N_PROPERTY,
270            "addDefaultProperty");
271
272        // extension mapping rules
273        digester.addCallMethod(
274            "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_MAPPINGS + "/" + N_MAPPING,
275            I_CmsResourceType.ADD_MAPPING_METHOD,
276            1);
277        digester.addCallParam("*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_MAPPINGS + "/" + N_MAPPING, 0, A_SUFFIX);
278
279        digester.addCallMethod(
280            "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_COPY_RESOURCES,
281            "setAdjustLinksFolder",
282            1);
283        digester.addCallParam("*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_COPY_RESOURCES, 0, A_ADJUST_LINKS_FOLDER);
284
285        // copy resource rules
286        digester.addCallMethod(
287            "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_COPY_RESOURCES + "/" + N_COPY_RESOURCE,
288            "addCopyResource",
289            3);
290        digester.addCallParam(
291            "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_COPY_RESOURCES + "/" + N_COPY_RESOURCE,
292            0,
293            A_SOURCE);
294        digester.addCallParam(
295            "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_COPY_RESOURCES + "/" + N_COPY_RESOURCE,
296            1,
297            A_TARGET);
298        digester.addCallParam(
299            "*/" + N_RESOURCETYPES + "/" + N_TYPE + "/" + N_COPY_RESOURCES + "/" + N_COPY_RESOURCE,
300            2,
301            A_TYPE);
302    }
303
304    /**
305     * Creates the xml output for resourcetype nodes.<p>
306     *
307     * @param startNode the startnode to add all rescource types to
308     * @param resourceTypes the list of resource types
309     * @param module flag, signaling to add them module resource types or not
310     */
311    public static void generateResourceTypeXml(
312        Element startNode,
313        List<I_CmsResourceType> resourceTypes,
314        boolean module) {
315
316        for (int i = 0; i < resourceTypes.size(); i++) {
317            I_CmsResourceType resType = resourceTypes.get(i);
318            // only add this resource type to the xml output, if it is no additional type defined
319            // in a module
320            if (resType.isAdditionalModuleResourceType() == module) {
321                Element resourceType = startNode.addElement(N_TYPE).addAttribute(A_CLASS, resType.getClassName());
322                // add type id and type name
323                resourceType.addAttribute(A_NAME, resType.getTypeName());
324                resourceType.addAttribute(A_ID, String.valueOf(resType.getTypeId()));
325                // add resource mappings
326                List<String> mappings = resType.getConfiguredMappings();
327                if ((mappings != null) && (mappings.size() > 0)) {
328                    Element mappingsNode = resourceType.addElement(N_MAPPINGS);
329                    for (int j = 0; j < mappings.size(); j++) {
330                        Element mapping = mappingsNode.addElement(N_MAPPING);
331                        mapping.addAttribute(A_SUFFIX, mappings.get(j));
332                    }
333                }
334                // add default properties
335                List<CmsProperty> properties = resType.getConfiguredDefaultProperties();
336                if (properties != null) {
337                    if (properties.size() > 0) {
338                        Element propertiesNode = resourceType.addElement(N_PROPERTIES);
339                        Iterator<CmsProperty> p = properties.iterator();
340                        while (p.hasNext()) {
341                            CmsProperty property = p.next();
342                            Element propertyNode = propertiesNode.addElement(N_PROPERTY);
343                            propertyNode.addElement(N_NAME).addText(property.getName());
344                            if (property.getStructureValue() != null) {
345                                propertyNode.addElement(N_VALUE).addCDATA(property.getStructureValue());
346                            }
347                            if (property.getResourceValue() != null) {
348                                propertyNode.addElement(N_VALUE).addAttribute(A_TYPE, CmsProperty.TYPE_SHARED).addCDATA(
349                                    property.getResourceValue());
350                            }
351                        }
352                    }
353                }
354                // add copy resources
355                List<CmsConfigurationCopyResource> copyRes = resType.getConfiguredCopyResources();
356                if ((copyRes != null) && (copyRes.size() > 0)) {
357                    Element copyResNode = resourceType.addElement(N_COPY_RESOURCES);
358                    Iterator<CmsConfigurationCopyResource> p = copyRes.iterator();
359                    String adjustLinksFolder = resType.getAdjustLinksFolder();
360                    if (adjustLinksFolder != null) {
361                        copyResNode.addAttribute(A_ADJUST_LINKS_FOLDER, adjustLinksFolder);
362                    }
363                    while (p.hasNext()) {
364                        CmsConfigurationCopyResource cRes = p.next();
365                        Element cNode = copyResNode.addElement(N_COPY_RESOURCE);
366                        cNode.addAttribute(A_SOURCE, cRes.getSource());
367                        if (!cRes.isTargetWasNull()) {
368                            cNode.addAttribute(A_TARGET, cRes.getTarget());
369                        }
370                        if (!cRes.isTypeWasNull()) {
371                            cNode.addAttribute(A_TYPE, cRes.getTypeString());
372                        }
373                    }
374                }
375                // add optional parameters
376                CmsParameterConfiguration configuration = resType.getConfiguration();
377                if (configuration != null) {
378                    List<String> ignore = null;
379                    if ((resType instanceof CmsResourceTypeXmlContainerPage)) {
380                        ignore = new ArrayList<String>(1);
381                        ignore.add(CmsResourceTypeXmlContent.CONFIGURATION_SCHEMA);
382                    }
383                    configuration.appendToXml(resourceType, ignore);
384                }
385            }
386        }
387    }
388
389    /**
390     * Adds a directory default file.<p>
391     *
392     * @param defaultFile the directory default file to add
393     */
394    public void addDefaultFile(String defaultFile) {
395
396        m_defaultFiles.add(defaultFile);
397        if (CmsLog.INIT.isInfoEnabled()) {
398            CmsLog.INIT.info(
399                Messages.get().getBundle().key(
400                    Messages.INIT_VFS_DEFAULT_FILE_2,
401                    new Integer(m_defaultFiles.size()),
402                    defaultFile));
403        }
404    }
405
406    /**
407     * Adds one file translation rule.<p>
408     *
409     * @param translation the file translation rule to add
410     */
411    public void addFileTranslation(String translation) {
412
413        m_fileTranslations.add(translation);
414        if (CmsLog.INIT.isInfoEnabled()) {
415            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_ADD_FILE_TRANSLATION_1, translation));
416        }
417    }
418
419    /**
420     * Adds one folder translation rule.<p>
421     *
422     * @param translation the folder translation rule to add
423     */
424    public void addFolderTranslation(String translation) {
425
426        m_folderTranslations.add(translation);
427        if (CmsLog.INIT.isInfoEnabled()) {
428            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_ADD_FOLDER_TRANSLATION_1, translation));
429        }
430    }
431
432    /**
433     * @see org.opencms.configuration.I_CmsXmlConfiguration#addXmlDigesterRules(org.apache.commons.digester.Digester)
434     */
435    public void addXmlDigesterRules(Digester digester) {
436
437        // add finish rule
438        digester.addCallMethod("*/" + N_VFS, "initializeFinished");
439
440        // creation of the resource manager
441        digester.addObjectCreate("*/" + N_VFS + "/" + N_RESOURCES, CmsResourceManager.class);
442        digester.addCallMethod(
443            "*/" + N_VFS + "/" + N_RESOURCES,
444            I_CmsConfigurationParameterHandler.INIT_CONFIGURATION_METHOD);
445        digester.addSetNext("*/" + N_VFS + "/" + N_RESOURCES, "setResourceManager");
446
447        // add rules for resource loaders
448        digester.addObjectCreate(
449            "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_RESOURCELOADERS + "/" + N_LOADER,
450            A_CLASS,
451            CmsConfigurationException.class);
452        digester.addCallMethod(
453            "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_RESOURCELOADERS + "/" + N_LOADER,
454            I_CmsConfigurationParameterHandler.INIT_CONFIGURATION_METHOD);
455        digester.addSetNext("*/" + N_VFS + "/" + N_RESOURCES + "/" + N_RESOURCELOADERS + "/" + N_LOADER, "addLoader");
456
457        // add rules for resource types
458        addResourceTypeXmlRules(digester);
459
460        // add rules for VFS content collectors
461        digester.addCallMethod(
462            "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_COLLECTORS + "/" + N_COLLECTOR,
463            "addContentCollector",
464            2);
465        digester.addCallParam("*/" + N_VFS + "/" + N_RESOURCES + "/" + N_COLLECTORS + "/" + N_COLLECTOR, 0, A_CLASS);
466        digester.addCallParam("*/" + N_VFS + "/" + N_RESOURCES + "/" + N_COLLECTORS + "/" + N_COLLECTOR, 1, A_ORDER);
467
468        // add the name generator
469        digester.addObjectCreate(
470            "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_NAMEGENERATOR,
471            CmsDefaultFileNameGenerator.class);
472        digester.addSetNext("*/" + N_VFS + "/" + N_RESOURCES + "/" + N_NAMEGENERATOR, "setNameGenerator");
473
474        // add MIME type rules
475        digester.addCallMethod(
476            "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_MIMETYPES + "/" + N_MIMETYPE,
477            "addMimeType",
478            2);
479        digester.addCallParam("*/" + N_VFS + "/" + N_RESOURCES + "/" + N_MIMETYPES + "/" + N_MIMETYPE, 0, A_EXTENSION);
480        digester.addCallParam("*/" + N_VFS + "/" + N_RESOURCES + "/" + N_MIMETYPES + "/" + N_MIMETYPE, 1, A_TYPE);
481
482        // add relation type rules
483        digester.addCallMethod(
484            "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_RELATIONTYPES + "/" + N_RELATIONTYPE,
485            "addRelationType",
486            2);
487        digester.addCallParam(
488            "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_RELATIONTYPES + "/" + N_RELATIONTYPE,
489            0,
490            A_NAME);
491        digester.addCallParam(
492            "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_RELATIONTYPES + "/" + N_RELATIONTYPE,
493            1,
494            A_TYPE);
495
496        // add html converter rules
497        digester.addCallMethod(
498            "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_HTML_CONVERTERS + "/" + N_HTML_CONVERTER,
499            "addHtmlConverter",
500            2);
501        digester.addCallParam(
502            "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_HTML_CONVERTERS + "/" + N_HTML_CONVERTER,
503            0,
504            A_NAME);
505        digester.addCallParam(
506            "*/" + N_VFS + "/" + N_RESOURCES + "/" + N_HTML_CONVERTERS + "/" + N_HTML_CONVERTER,
507            1,
508            A_CLASS);
509
510        // generic <param> parameter rules
511        digester.addCallMethod(
512            "*/" + I_CmsXmlConfiguration.N_PARAM,
513            I_CmsConfigurationParameterHandler.ADD_PARAMETER_METHOD,
514            2);
515        digester.addCallParam("*/" + I_CmsXmlConfiguration.N_PARAM, 0, I_CmsXmlConfiguration.A_NAME);
516        digester.addCallParam("*/" + I_CmsXmlConfiguration.N_PARAM, 1);
517
518        // add rule for default files
519        digester.addCallMethod("*/" + N_VFS + "/" + N_DEFAULTFILES + "/" + N_DEFAULTFILE, "addDefaultFile", 1);
520        digester.addCallParam("*/" + N_VFS + "/" + N_DEFAULTFILES + "/" + N_DEFAULTFILE, 0, A_NAME);
521
522        // add rules for file translations
523        digester.addCallMethod(
524            "*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_FILETRANSLATIONS + "/" + N_TRANSLATION,
525            "addFileTranslation",
526            0);
527        digester.addCallMethod(
528            "*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_FILETRANSLATIONS,
529            "setFileTranslationEnabled",
530            1);
531        digester.addCallParam("*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_FILETRANSLATIONS, 0, A_ENABLED);
532
533        // add rules for file translations
534        digester.addCallMethod(
535            "*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_FOLDERTRANSLATIONS + "/" + N_TRANSLATION,
536            "addFolderTranslation",
537            0);
538        digester.addCallMethod(
539            "*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_FOLDERTRANSLATIONS,
540            "setFolderTranslationEnabled",
541            1);
542        digester.addCallParam("*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_FOLDERTRANSLATIONS, 0, A_ENABLED);
543
544        // add rules for file translations
545        digester.addCallMethod(
546            "*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_XSDTRANSLATIONS + "/" + N_TRANSLATION,
547            "addXsdTranslation",
548            0);
549        digester.addCallMethod(
550            "*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_XSDTRANSLATIONS,
551            "setXsdTranslationEnabled",
552            1);
553        digester.addCallParam("*/" + N_VFS + "/" + N_TRANSLATIONS + "/" + N_XSDTRANSLATIONS, 0, A_ENABLED);
554
555        // XML content type manager creation rules
556        digester.addObjectCreate("*/" + N_VFS + "/" + N_XMLCONTENT, CmsXmlContentTypeManager.class);
557        digester.addSetNext("*/" + N_VFS + "/" + N_XMLCONTENT, "setXmlContentTypeManager");
558
559        // XML content widgets add rules
560        digester.addCallMethod("*/" + N_VFS + "/" + N_XMLCONTENT + "/" + N_WIDGETS + "/" + N_WIDGET, "addWidget", 3);
561        digester.addCallParam("*/" + N_VFS + "/" + N_XMLCONTENT + "/" + N_WIDGETS + "/" + N_WIDGET, 0, A_CLASS);
562        digester.addCallParam("*/" + N_VFS + "/" + N_XMLCONTENT + "/" + N_WIDGETS + "/" + N_WIDGET, 1, A_ALIAS);
563        digester.addCallParam("*/" + N_VFS + "/" + N_XMLCONTENT + "/" + N_WIDGETS + "/" + N_WIDGET, 2, A_CONFIGURATION);
564
565        // XML content schema type add rules
566        digester.addCallMethod(
567            "*/" + N_VFS + "/" + N_XMLCONTENT + "/" + N_SCHEMATYPES + "/" + N_SCHEMATYPE,
568            "addSchemaType",
569            2);
570        digester.addCallParam("*/" + N_VFS + "/" + N_XMLCONTENT + "/" + N_SCHEMATYPES + "/" + N_SCHEMATYPE, 0, A_CLASS);
571        digester.addCallParam(
572            "*/" + N_VFS + "/" + N_XMLCONTENT + "/" + N_SCHEMATYPES + "/" + N_SCHEMATYPE,
573            1,
574            A_DEFAULTWIDGET);
575    }
576
577    /**
578     * Adds one XSD translation rule.<p>
579     *
580     * @param translation the XSD translation rule to add
581     */
582    public void addXsdTranslation(String translation) {
583
584        m_xsdTranslations.add(translation);
585        if (CmsLog.INIT.isInfoEnabled()) {
586            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_ADD_XSD_TRANSLATION_1, translation));
587        }
588    }
589
590    /**
591     * @see org.opencms.configuration.I_CmsXmlConfiguration#generateXml(org.dom4j.Element)
592     */
593    public Element generateXml(Element parent) {
594
595        if (OpenCms.getRunLevel() >= OpenCms.RUNLEVEL_3_SHELL_ACCESS) {
596            m_resourceManager = OpenCms.getResourceManager();
597            m_xmlContentTypeManager = OpenCms.getXmlContentTypeManager();
598            m_defaultFiles = OpenCms.getDefaultFiles();
599        }
600
601        // generate vfs node and subnodes
602        Element vfs = parent.addElement(N_VFS);
603
604        // add resources main element
605        Element resources = vfs.addElement(N_RESOURCES);
606
607        // add resource loader
608        Element resourceloadersElement = resources.addElement(N_RESOURCELOADERS);
609        for (I_CmsResourceLoader loader : m_resourceManager.getLoaders()) {
610            // add the loader node
611            Element loaderNode = resourceloadersElement.addElement(N_LOADER);
612            loaderNode.addAttribute(A_CLASS, loader.getClass().getName());
613            CmsParameterConfiguration loaderConfiguration = loader.getConfiguration();
614            if (loaderConfiguration != null) {
615                loaderConfiguration.appendToXml(loaderNode);
616            }
617        }
618
619        // add resource types
620        Element resourcetypesElement = resources.addElement(N_RESOURCETYPES);
621        List<I_CmsResourceType> resourceTypes = new ArrayList<I_CmsResourceType>();
622        if (m_resourceManager.getResTypeUnknownFolder() != null) {
623            resourceTypes.add(m_resourceManager.getResTypeUnknownFolder());
624        }
625        if (m_resourceManager.getResTypeUnknownFile() != null) {
626            resourceTypes.add(m_resourceManager.getResTypeUnknownFile());
627        }
628        resourceTypes.addAll(m_resourceManager.getResourceTypes());
629        generateResourceTypeXml(resourcetypesElement, resourceTypes, false);
630
631        // add VFS content collectors
632        Element collectorsElement = resources.addElement(N_COLLECTORS);
633        for (I_CmsResourceCollector collector : m_resourceManager.getRegisteredContentCollectors()) {
634            collectorsElement.addElement(N_COLLECTOR).addAttribute(
635                A_CLASS,
636                collector.getClass().getName()).addAttribute(A_ORDER, String.valueOf(collector.getOrder()));
637        }
638
639        Element namegeneratorElement = resources.addElement(N_NAMEGENERATOR);
640        String nameGeneratorClass = m_resourceManager.getNameGenerator().getClass().getName();
641        namegeneratorElement.addAttribute(A_CLASS, nameGeneratorClass);
642
643        // add MIME types
644        Element mimeTypesElement = resources.addElement(N_MIMETYPES);
645        for (CmsMimeType type : m_resourceManager.getMimeTypes()) {
646            mimeTypesElement.addElement(N_MIMETYPE).addAttribute(A_EXTENSION, type.getExtension()).addAttribute(
647                A_TYPE,
648                type.getType());
649        }
650
651        // add relation types
652        Element relationTypesElement = resources.addElement(N_RELATIONTYPES);
653        for (CmsRelationType type : m_resourceManager.getRelationTypes()) {
654            relationTypesElement.addElement(N_RELATIONTYPE).addAttribute(A_NAME, type.getName()).addAttribute(
655                A_TYPE,
656                type.getType());
657        }
658
659        // HTML converter configuration
660        boolean writeConfig = false;
661        for (CmsHtmlConverterOption converter : m_resourceManager.getHtmlConverters()) {
662            if (!converter.isDefault()) {
663                // found a non default converter configuration, set flag to write configuration
664                writeConfig = true;
665                break;
666            }
667        }
668        if (writeConfig) {
669            // configuration is written because non default options were found
670            Element htmlConvertersElement = resources.addElement(N_HTML_CONVERTERS);
671            for (CmsHtmlConverterOption converter : m_resourceManager.getHtmlConverters()) {
672                Element converterElement = htmlConvertersElement.addElement(N_HTML_CONVERTER).addAttribute(
673                    A_NAME,
674                    converter.getName());
675                converterElement.addAttribute(A_CLASS, converter.getClassName());
676            }
677        }
678
679        // add default file names
680        Element defaultFileElement = vfs.addElement(N_DEFAULTFILES);
681        for (String element : m_defaultFiles) {
682            defaultFileElement.addElement(N_DEFAULTFILE).addAttribute(A_NAME, element);
683        }
684
685        // add translation rules
686        Element translationsElement = vfs.addElement(N_TRANSLATIONS);
687
688        // file translation rules
689        Element fileTransElement = translationsElement.addElement(N_FILETRANSLATIONS).addAttribute(
690            A_ENABLED,
691            String.valueOf(m_fileTranslationEnabled));
692        for (String translation : m_fileTranslations) {
693            fileTransElement.addElement(N_TRANSLATION).setText(translation);
694        }
695
696        // folder translation rules
697        Element folderTransElement = translationsElement.addElement(N_FOLDERTRANSLATIONS).addAttribute(
698            A_ENABLED,
699            String.valueOf(m_folderTranslationEnabled));
700        for (String translation : m_folderTranslations) {
701            folderTransElement.addElement(N_TRANSLATION).setText(translation);
702        }
703
704        // XSD translation rules
705        Element xsdTransElement = translationsElement.addElement(N_XSDTRANSLATIONS).addAttribute(
706            A_ENABLED,
707            String.valueOf(m_xsdTranslationEnabled));
708        for (String translation : m_xsdTranslations) {
709            xsdTransElement.addElement(N_TRANSLATION).setText(translation);
710        }
711
712        // XML content configuration
713        Element xmlContentsElement = vfs.addElement(N_XMLCONTENT);
714
715        // XML widgets
716        Element xmlWidgetsElement = xmlContentsElement.addElement(N_WIDGETS);
717        for (String widget : m_xmlContentTypeManager.getRegisteredWidgetNames()) {
718            Element widgetElement = xmlWidgetsElement.addElement(N_WIDGET).addAttribute(A_CLASS, widget);
719            String alias = m_xmlContentTypeManager.getRegisteredWidgetAlias(widget);
720            if (alias != null) {
721                widgetElement.addAttribute(A_ALIAS, alias);
722            }
723            String defaultConfiguration = m_xmlContentTypeManager.getWidgetDefaultConfiguration(widget);
724            if (CmsStringUtil.isNotEmpty(defaultConfiguration)) {
725                widgetElement.addAttribute(A_CONFIGURATION, defaultConfiguration);
726            }
727        }
728
729        // XML content types
730        Element xmlSchemaTypesElement = xmlContentsElement.addElement(N_SCHEMATYPES);
731        for (I_CmsXmlSchemaType type : m_xmlContentTypeManager.getRegisteredSchemaTypes()) {
732            I_CmsWidget widget = m_xmlContentTypeManager.getWidgetDefault(type.getTypeName());
733            xmlSchemaTypesElement.addElement(N_SCHEMATYPE).addAttribute(
734                A_CLASS,
735                type.getClass().getName()).addAttribute(A_DEFAULTWIDGET, widget.getClass().getName());
736        }
737
738        // return the vfs node
739        return vfs;
740    }
741
742    /**
743     * Returns the (unmodifiable) list of configured directory default files.<p>
744     *
745     * @return the (unmodifiable) list of configured directory default files
746     */
747    public List<String> getDefaultFiles() {
748
749        return Collections.unmodifiableList(m_defaultFiles);
750    }
751
752    /**
753     * @see org.opencms.configuration.I_CmsXmlConfiguration#getDtdFilename()
754     */
755    public String getDtdFilename() {
756
757        return CONFIGURATION_DTD_NAME;
758    }
759
760    /**
761     * Returns the file resource translator that has been initialized
762     * with the configured file translation rules.<p>
763     *
764     * @return the file resource translator
765     */
766    public CmsResourceTranslator getFileTranslator() {
767
768        String[] array = new String[0];
769        if (m_fileTranslationEnabled) {
770            array = new String[m_fileTranslations.size()];
771            for (int i = 0; i < m_fileTranslations.size(); i++) {
772                array[i] = m_fileTranslations.get(i);
773            }
774        }
775        return new CmsResourceTranslator(array, true);
776    }
777
778    /**
779     * Returns the folder resource translator that has been initialized
780     * with the configured folder translation rules.<p>
781     *
782     * @return the folder resource translator
783     */
784    public CmsResourceTranslator getFolderTranslator() {
785
786        String[] array = new String[0];
787        if (m_folderTranslationEnabled) {
788            array = new String[m_folderTranslations.size()];
789            for (int i = 0; i < m_folderTranslations.size(); i++) {
790                array[i] = m_folderTranslations.get(i);
791            }
792        }
793        return new CmsResourceTranslator(array, false);
794    }
795
796    /**
797     * Returns the initialized resource manager.<p>
798     *
799     * @return the initialized resource manager
800     */
801    public CmsResourceManager getResourceManager() {
802
803        return m_resourceManager;
804    }
805
806    /**
807     * Returns the configured XML content type manager.<p>
808     *
809     * @return the configured XML content type manager
810     */
811    public CmsXmlContentTypeManager getXmlContentTypeManager() {
812
813        return m_xmlContentTypeManager;
814    }
815
816    /**
817     * Returns the XSD translator that has been initialized
818     * with the configured XSD translation rules.<p>
819     *
820     * @return the XSD translator
821     */
822    public CmsResourceTranslator getXsdTranslator() {
823
824        String[] array = m_xsdTranslationEnabled ? new String[m_xsdTranslations.size()] : new String[0];
825        for (int i = 0; i < m_xsdTranslations.size(); i++) {
826            array[i] = m_xsdTranslations.get(i);
827        }
828        return new CmsResourceTranslator(array, true);
829    }
830
831    /**
832     * Will be called when configuration of this object is finished.<p>
833     */
834    public void initializeFinished() {
835
836        if (CmsLog.INIT.isInfoEnabled()) {
837            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_CONFIG_FINISHED_0));
838        }
839    }
840
841    /**
842     * Enables or disables the file translation rules.<p>
843     *
844     * @param value if <code>"true"</code>, file translation is enabled, otherwise it is disabled
845     */
846    public void setFileTranslationEnabled(String value) {
847
848        m_fileTranslationEnabled = Boolean.valueOf(value).booleanValue();
849        if (CmsLog.INIT.isInfoEnabled()) {
850            if (m_fileTranslationEnabled) {
851                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_FILE_TRANSLATION_ENABLE_0));
852            } else {
853                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_FILE_TRANSLATION_DISABLE_0));
854            }
855        }
856    }
857
858    /**
859     * Enables or disables the folder translation rules.<p>
860     *
861     * @param value if <code>"true"</code>, folder translation is enabled, otherwise it is disabled
862     */
863    public void setFolderTranslationEnabled(String value) {
864
865        m_folderTranslationEnabled = Boolean.valueOf(value).booleanValue();
866        if (CmsLog.INIT.isInfoEnabled()) {
867            if (m_folderTranslationEnabled) {
868                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_FOLDER_TRANSLATION_ENABLE_0));
869            } else {
870                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_FOLDER_TRANSLATION_DISABLE_0));
871            }
872        }
873    }
874
875    /**
876     * Sets the generated resource manager.<p>
877     *
878     * @param manager the resource manager to set
879     */
880    public void setResourceManager(CmsResourceManager manager) {
881
882        m_resourceManager = manager;
883    }
884
885    /**
886     * Sets the generated XML content type manager.<p>
887     *
888     * @param manager the generated XML content type manager to set
889     */
890    public void setXmlContentTypeManager(CmsXmlContentTypeManager manager) {
891
892        if (CmsLog.INIT.isInfoEnabled()) {
893            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_XML_CONTENT_FINISHED_0));
894        }
895        m_xmlContentTypeManager = manager;
896    }
897
898    /**
899     * Enables or disables the XSD translation rules.<p>
900     *
901     * @param value if <code>"true"</code>, XSD translation is enabled, otherwise it is disabled
902     */
903    public void setXsdTranslationEnabled(String value) {
904
905        m_xsdTranslationEnabled = Boolean.valueOf(value).booleanValue();
906        if (CmsLog.INIT.isInfoEnabled()) {
907            if (m_xsdTranslationEnabled) {
908                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_XSD_TRANSLATION_ENABLE_0));
909            } else {
910                CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_XSD_TRANSLATION_DISABLE_0));
911            }
912        }
913    }
914
915    /**
916     * @see org.opencms.configuration.A_CmsXmlConfiguration#initMembers()
917     */
918    @Override
919    protected void initMembers() {
920
921        setXmlFileName(DEFAULT_XML_FILE_NAME);
922        m_fileTranslations = new ArrayList<String>();
923        m_folderTranslations = new ArrayList<String>();
924        m_xsdTranslations = new ArrayList<String>();
925        m_defaultFiles = new ArrayList<String>();
926        if (CmsLog.INIT.isInfoEnabled()) {
927            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_VFS_CONFIG_INIT_0));
928        }
929    }
930}