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, 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.ade.sitemap;
029
030import org.opencms.ade.configuration.CmsADEConfigData;
031import org.opencms.ade.configuration.CmsConfigurationReader;
032import org.opencms.ade.configuration.CmsModelPageConfig;
033import org.opencms.ade.configuration.CmsResourceTypeConfig;
034import org.opencms.ade.sitemap.shared.CmsModelInfo;
035import org.opencms.ade.sitemap.shared.CmsModelPageEntry;
036import org.opencms.file.CmsFile;
037import org.opencms.file.CmsObject;
038import org.opencms.file.CmsProperty;
039import org.opencms.file.CmsPropertyDefinition;
040import org.opencms.file.CmsResource;
041import org.opencms.file.CmsResourceFilter;
042import org.opencms.file.CmsVfsResourceNotFoundException;
043import org.opencms.file.types.CmsResourceTypeFolder;
044import org.opencms.file.types.CmsResourceTypeXmlContainerPage;
045import org.opencms.file.types.I_CmsResourceType;
046import org.opencms.gwt.CmsVfsService;
047import org.opencms.gwt.shared.CmsListInfoBean;
048import org.opencms.gwt.shared.property.CmsClientProperty;
049import org.opencms.loader.CmsLoaderException;
050import org.opencms.lock.CmsLock;
051import org.opencms.main.CmsException;
052import org.opencms.main.CmsLog;
053import org.opencms.main.OpenCms;
054import org.opencms.relations.CmsLink;
055import org.opencms.util.CmsStringUtil;
056import org.opencms.util.CmsUUID;
057import org.opencms.xml.CmsXmlException;
058import org.opencms.xml.content.CmsXmlContent;
059import org.opencms.xml.content.CmsXmlContentFactory;
060import org.opencms.xml.types.CmsXmlVfsFileValue;
061import org.opencms.xml.types.I_CmsXmlContentValue;
062
063import java.util.ArrayList;
064import java.util.Arrays;
065import java.util.Collections;
066import java.util.List;
067import java.util.Locale;
068import java.util.Map;
069
070import org.apache.commons.logging.Log;
071
072import com.google.common.collect.Lists;
073import com.google.common.collect.Maps;
074
075/**
076 * Helper class for model page operations in the sitemap editor.<p>
077 */
078public class CmsModelPageHelper {
079
080    /** The logger for this class. */
081    private static final Log LOG = CmsLog.getLog(CmsModelPageHelper.class);
082
083    /** The sitmeap config data. */
084    private CmsADEConfigData m_adeConfig;
085
086    /** The CMS context used. */
087    private CmsObject m_cms;
088
089    /** The site map root. */
090    private CmsResource m_rootResource;
091
092    /** The site root. */
093    private String m_siteRoot;
094
095    /**
096     * Creates a new instance.<p>
097     *
098     * @param cms the CMS context to use
099     * @param rootResource the root resource for the sitemap
100     *
101     * @throws CmsException if something goes wrong
102     */
103    public CmsModelPageHelper(CmsObject cms, CmsResource rootResource)
104    throws CmsException {
105
106        m_cms = OpenCms.initCmsObject(cms);
107        m_cms.getRequestContext().setSiteRoot("");
108
109        m_rootResource = rootResource;
110        m_adeConfig = OpenCms.getADEManager().lookupConfiguration(m_cms, rootResource.getRootPath());
111        m_siteRoot = OpenCms.getSiteManager().getSiteRoot(rootResource.getRootPath());
112        if (m_siteRoot == null) {
113            m_siteRoot = "";
114        }
115
116    }
117
118    /**
119     * Adds a model page to the sitemap config.<p>
120     *
121     * @param sitemapConfig the sitemap configuration resource
122     * @param modelPage the model page to add
123     * @param disabled true if the model page should be added as 'disabled'
124     *
125     * @throws CmsException if something goes wrong
126     */
127    public void addModelPageToSitemapConfiguration(CmsResource sitemapConfig, CmsResource modelPage, boolean disabled)
128    throws CmsException {
129
130        CmsFile sitemapConfigFile = m_cms.readFile(sitemapConfig);
131        CmsXmlContent content = CmsXmlContentFactory.unmarshal(m_cms, sitemapConfigFile);
132        CmsConfigurationReader reader = new CmsConfigurationReader(m_cms);
133        reader.parseConfiguration(m_adeConfig.getBasePath(), content);
134        List<CmsModelPageConfig> modelPageConfigs = reader.getModelPageConfigs();
135
136        int i = 0;
137        boolean isDefault = false;
138        for (CmsModelPageConfig config : modelPageConfigs) {
139            if (config.getResource().getStructureId().equals(modelPage.getStructureId())) {
140                isDefault = config.isDefault();
141                break;
142            }
143            i += 1;
144        }
145        if (i >= modelPageConfigs.size()) {
146            content.addValue(m_cms, CmsConfigurationReader.N_MODEL_PAGE, Locale.ENGLISH, i);
147        }
148        String prefix = CmsConfigurationReader.N_MODEL_PAGE + "[" + (1 + i) + "]";
149        content.getValue(prefix + "/" + CmsConfigurationReader.N_PAGE, Locale.ENGLISH).setStringValue(
150            m_cms,
151            modelPage.getRootPath());
152        content.getValue(prefix + "/" + CmsConfigurationReader.N_DISABLED, Locale.ENGLISH).setStringValue(
153            m_cms,
154            "" + disabled);
155        content.getValue(prefix + "/" + CmsConfigurationReader.N_IS_DEFAULT, Locale.ENGLISH).setStringValue(
156            m_cms,
157            "" + isDefault);
158        writeSitemapConfig(content, sitemapConfigFile);
159    }
160
161    /**
162     * Creates a new model group page.<p>
163     *
164     * @param name the page name
165     * @param description the page description
166     * @param copyId structure id of the resource to use as a model for the model page, if any (may be null)
167     *
168     * @return the new resource
169     *
170     * @throws CmsException in case something goes wrong
171     */
172    public CmsResource createModelGroupPage(String name, String description, CmsUUID copyId) throws CmsException {
173
174        CmsResource newPage = null;
175        CmsResourceTypeConfig config = m_adeConfig.getResourceType(
176            CmsResourceTypeXmlContainerPage.MODEL_GROUP_TYPE_NAME);
177        if ((config != null) && !config.isDisabled()) {
178            if (copyId == null) {
179                newPage = config.createNewElement(m_cms, m_rootResource.getRootPath());
180            } else {
181                CmsResource copyResource = m_cms.readResource(copyId);
182                newPage = config.createNewElement(m_cms, copyResource, m_rootResource.getRootPath());
183            }
184            m_cms.lockResource(newPage);
185            CmsProperty titleProp = new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, name, null);
186            CmsProperty descriptionProp = new CmsProperty(
187                CmsPropertyDefinition.PROPERTY_DESCRIPTION,
188                description,
189                null);
190            m_cms.writePropertyObject(m_cms.getSitePath(newPage), titleProp);
191            m_cms.writePropertyObject(m_cms.getSitePath(newPage), descriptionProp);
192            tryUnlock(newPage);
193        }
194        return newPage;
195    }
196
197    /**
198     * Creates a new potential model page in the default folder for new model pages.<p>
199     *
200     * @param name the title for the model page
201     * @param description the description for the model page
202     * @param copyId structure id of the resource to use as a model for the model page, if any (may be null)
203     *
204     * @return the created resource
205     * @throws CmsException if something goes wrong
206     */
207    public CmsResource createPageInModelFolder(String name, String description, CmsUUID copyId) throws CmsException {
208
209        CmsResource modelFolder = ensureModelFolder(m_rootResource);
210        String pattern = "templatemodel_%(number).html";
211        String newFilePath = OpenCms.getResourceManager().getNameGenerator().getNewFileName(
212            m_cms,
213            CmsStringUtil.joinPaths(modelFolder.getRootPath(), pattern),
214            4);
215        CmsProperty titleProp = new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, name, null);
216        CmsProperty descriptionProp = new CmsProperty(CmsPropertyDefinition.PROPERTY_DESCRIPTION, description, null);
217        CmsResource newPage = null;
218        if (copyId == null) {
219            newPage = m_cms.createResource(
220                newFilePath,
221                getType(CmsResourceTypeXmlContainerPage.getStaticTypeName()),
222                null,
223                Arrays.asList(titleProp, descriptionProp));
224        } else {
225            CmsResource copyResource = m_cms.readResource(copyId);
226            m_cms.copyResource(copyResource.getRootPath(), newFilePath);
227            m_cms.writePropertyObject(newFilePath, titleProp);
228            m_cms.writePropertyObject(newFilePath, descriptionProp);
229
230            newPage = m_cms.readResource(newFilePath);
231        }
232        tryUnlock(newPage);
233        return newPage;
234    }
235
236    /**
237     * Disables the given model page.<p>
238     *
239     * @param sitemapConfig the configuration resource
240     * @param structureId the model page id
241     * @param disabled <code>true</code> to disabe the entry
242     *
243     * @throws CmsException if something goes wrong
244     */
245    public void disableModelPage(CmsResource sitemapConfig, CmsUUID structureId, boolean disabled) throws CmsException {
246
247        CmsFile sitemapConfigFile = m_cms.readFile(sitemapConfig);
248        CmsXmlContent content = CmsXmlContentFactory.unmarshal(m_cms, sitemapConfigFile);
249        CmsConfigurationReader reader = new CmsConfigurationReader(m_cms);
250        reader.parseConfiguration(m_adeConfig.getBasePath(), content);
251        List<CmsModelPageConfig> modelPageConfigs = reader.getModelPageConfigs();
252
253        int i = 0;
254        for (CmsModelPageConfig config : modelPageConfigs) {
255            if (config.getResource().getStructureId().equals(structureId)) {
256                break;
257            }
258            i += 1;
259        }
260        I_CmsXmlContentValue value;
261        if (i < modelPageConfigs.size()) {
262            value = content.getValue(CmsConfigurationReader.N_MODEL_PAGE, Locale.ENGLISH, i);
263        } else {
264            value = content.addValue(m_cms, CmsConfigurationReader.N_MODEL_PAGE, Locale.ENGLISH, i);
265            String linkValuePath = value.getPath() + "/" + CmsConfigurationReader.N_MODEL_PAGE;
266            I_CmsXmlContentValue linkValue = content.hasValue(linkValuePath, Locale.ENGLISH)
267            ? content.getValue(linkValuePath, Locale.ENGLISH)
268            : content.addValue(m_cms, linkValuePath, Locale.ENGLISH, 0);
269            CmsResource model = m_cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
270            linkValue.setStringValue(m_cms, m_cms.getSitePath(model));
271        }
272        String disabledPath = value.getPath() + "/" + CmsConfigurationReader.N_DISABLED;
273        I_CmsXmlContentValue disabledValue = content.hasValue(disabledPath, Locale.ENGLISH)
274        ? content.getValue(disabledPath, Locale.ENGLISH)
275        : content.addValue(m_cms, disabledPath, Locale.ENGLISH, 0);
276        disabledValue.setStringValue(m_cms, Boolean.toString(disabled));
277        writeSitemapConfig(content, sitemapConfigFile);
278    }
279
280    /**
281     * Tries to either read or create the default folder for model pages in the current sitemap, and returns it.<p>
282     *
283     * @param rootResource the root of the sitemap
284     *
285     * @return the folder resource
286     *
287     * @throws CmsException if something goes wrong
288     */
289    public CmsResource ensureModelFolder(CmsResource rootResource) throws CmsException {
290
291        String modelFolderPath = CmsStringUtil.joinPaths(m_adeConfig.getBasePath(), ".content/.templates");
292
293        try {
294            CmsResource result = m_cms.readFolder(modelFolderPath);
295            return result;
296        } catch (CmsVfsResourceNotFoundException e) {
297            CmsProperty searchExclude = new CmsProperty(CmsPropertyDefinition.PROPERTY_SEARCH_EXCLUDE, "all", null);
298            CmsResource result = m_cms.createResource(
299                modelFolderPath,
300                getType(CmsResourceTypeFolder.getStaticTypeName()),
301                null,
302                Arrays.asList(searchExclude));
303            tryUnlock(result);
304            return result;
305        }
306
307    }
308
309    /**
310     * Returns the local model group pages.<p>
311     *
312     * @return the model group pages
313     */
314    public List<CmsModelPageEntry> getModelGroups() {
315
316        List<CmsModelPageEntry> result = new ArrayList<CmsModelPageEntry>();
317        CmsResourceTypeConfig config = m_adeConfig.getResourceType(
318            CmsResourceTypeXmlContainerPage.MODEL_GROUP_TYPE_NAME);
319        if ((config != null) && !config.isDisabled()) {
320            String modelGroupFolderPath = config.getFolderPath(m_cms, m_adeConfig.getBasePath());
321            if (m_cms.existsResource(modelGroupFolderPath)) {
322                try {
323                    Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms);
324                    List<CmsResource> modelResources = m_cms.readResources(
325                        modelGroupFolderPath,
326                        CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType(
327                            OpenCms.getResourceManager().getResourceType(
328                                CmsResourceTypeXmlContainerPage.MODEL_GROUP_TYPE_NAME)),
329                        false);
330                    for (CmsResource model : modelResources) {
331                        CmsModelPageEntry entry = createModelPageEntry(model, false, false, wpLocale);
332                        if (entry != null) {
333                            result.add(entry);
334                        }
335                    }
336                } catch (CmsException e) {
337                    LOG.error(e.getLocalizedMessage(), e);
338                }
339            }
340        }
341        return result;
342    }
343
344    /**
345     * Returns the model infos.<p>
346     *
347     * @return the model infos
348     */
349    public CmsModelInfo getModelInfo() {
350
351        return new CmsModelInfo(getModelPages(), getParentModelPages(), getModelGroups());
352    }
353
354    /**
355     * Reads the model pages from the ADE configuration.<p>
356     *
357     * @return the list of model pages
358     */
359    public List<CmsModelPageEntry> getModelPages() {
360
361        List<CmsModelPageConfig> modelPageConfigs = m_adeConfig.getModelPages(true);
362        return buildModelPageList(modelPageConfigs);
363    }
364
365    /**
366     * Returns the parent model pages.<p>
367     *
368     * @return the parent model pages
369     */
370    public List<CmsModelPageEntry> getParentModelPages() {
371
372        CmsADEConfigData adeConfig = m_adeConfig.parent();
373        if ((adeConfig == null) || adeConfig.isModuleConfiguration()) {
374            return Collections.emptyList();
375        }
376        List<CmsModelPageConfig> modelPageConfigs = adeConfig.getModelPages();
377        return buildModelPageList(modelPageConfigs);
378    }
379
380    /**
381     * Removes a model page from the sitemap configuration.<p>
382     *
383     * @param sitemapConfig the sitemap configuration resource
384     * @param structureId the structure id of the model page to remove
385     *
386     * @throws CmsException if something goes wrong
387     */
388    public void removeModelPage(CmsResource sitemapConfig, CmsUUID structureId) throws CmsException {
389
390        CmsFile sitemapConfigFile = m_cms.readFile(sitemapConfig);
391        CmsXmlContent content = CmsXmlContentFactory.unmarshal(m_cms, sitemapConfigFile);
392        CmsConfigurationReader reader = new CmsConfigurationReader(m_cms);
393        reader.parseConfiguration(m_adeConfig.getBasePath(), content);
394        List<CmsModelPageConfig> modelPageConfigs = reader.getModelPageConfigs();
395
396        int i = 0;
397        for (CmsModelPageConfig config : modelPageConfigs) {
398            if (config.getResource().getStructureId().equals(structureId)) {
399                break;
400            }
401            i += 1;
402        }
403        if (i < modelPageConfigs.size()) {
404            content.removeValue(CmsConfigurationReader.N_MODEL_PAGE, Locale.ENGLISH, i);
405        }
406        writeSitemapConfig(content, sitemapConfigFile);
407    }
408
409    /**
410     * Creates a model page entry bean from a model page resource.<p>
411     *
412     * @param resource the model page resource
413     * @param disabled if the model page is disabled
414     * @param isDefault if this is the default model page
415     * @param locale the current user locale
416     *
417     * @return the model page entry bean
418     */
419    CmsModelPageEntry createModelPageEntry(CmsResource resource, boolean disabled, boolean isDefault, Locale locale) {
420
421        try {
422            CmsModelPageEntry result = new CmsModelPageEntry();
423            result.setDefault(isDefault);
424            result.setDisabled(disabled);
425            List<CmsProperty> properties = m_cms.readPropertyObjects(resource, false);
426            Map<String, CmsClientProperty> clientProperties = Maps.newHashMap();
427            for (CmsProperty prop : properties) {
428                CmsClientProperty clientProp = CmsVfsSitemapService.createClientProperty(prop, false);
429                clientProperties.put(prop.getName(), clientProp);
430            }
431            result.setOwnProperties(clientProperties);
432            result.setRootPath(resource.getRootPath());
433            if (resource.getRootPath().startsWith(m_siteRoot)) {
434                CmsObject siteCms = OpenCms.initCmsObject(m_cms);
435                siteCms.getRequestContext().setSiteRoot(m_siteRoot);
436                result.setSitePath(siteCms.getSitePath(resource));
437            }
438            result.setResourceType(OpenCms.getResourceManager().getResourceType(resource).getTypeName());
439            result.setStructureId(resource.getStructureId());
440            CmsListInfoBean infoBean = CmsVfsService.getPageInfo(m_cms, resource);
441            CmsProperty descProperty = m_cms.readPropertyObject(
442                resource,
443                CmsPropertyDefinition.PROPERTY_DESCRIPTION,
444                false,
445                locale);
446            if (!CmsStringUtil.isEmptyOrWhitespaceOnly(descProperty.getValue())) {
447                infoBean.setSubTitle(descProperty.getValue());
448            }
449            infoBean.addAdditionalInfo(
450                Messages.get().getBundle(OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms)).key(
451                    Messages.GUI_VFS_PATH_0),
452                result.getSitePath() != null ? result.getSitePath() : result.getRootPath());
453            result.setListInfoBean(infoBean);
454            return result;
455        } catch (Exception e) {
456            LOG.error(e.getLocalizedMessage(), e);
457            return null;
458        }
459    }
460
461    /**
462     * Sets the default model page within the given configuration file.<p>
463     *
464     * @param configFile the configuration file
465     * @param modelId the default model id
466     *
467     * @return the updated model configuration
468     *
469     * @throws CmsException in case something goes wrong
470     */
471    CmsModelInfo setDefaultModelPage(CmsResource configFile, CmsUUID modelId) throws CmsException {
472
473        CmsFile file = m_cms.readFile(configFile);
474        CmsXmlContent content = CmsXmlContentFactory.unmarshal(m_cms, file);
475        Locale locale = getLocale(content);
476        int defaultValueIndex = -1;
477        String defaultModelTarget = null;
478        for (I_CmsXmlContentValue value : content.getValues(CmsConfigurationReader.N_MODEL_PAGE, locale)) {
479            I_CmsXmlContentValue linkValue = content.getValue(
480                CmsStringUtil.joinPaths(value.getPath(), CmsConfigurationReader.N_PAGE),
481                locale);
482            I_CmsXmlContentValue isDefaultValue = content.getValue(
483                CmsStringUtil.joinPaths(value.getPath(), CmsConfigurationReader.N_IS_DEFAULT),
484                locale);
485            CmsLink link = ((CmsXmlVfsFileValue)linkValue).getLink(m_cms);
486            if ((link != null) && link.getStructureId().equals(modelId)) {
487                // store index and site path
488                defaultValueIndex = value.getIndex();
489                defaultModelTarget = link.getTarget();
490            } else {
491                isDefaultValue.setStringValue(m_cms, Boolean.FALSE.toString());
492            }
493        }
494        if (defaultValueIndex != -1) {
495            // remove the value from the old position and insert it a the top
496            content.removeValue(CmsConfigurationReader.N_MODEL_PAGE, locale, defaultValueIndex);
497            content.addValue(m_cms, CmsConfigurationReader.N_MODEL_PAGE, locale, 0);
498            content.getValue(
499                CmsConfigurationReader.N_MODEL_PAGE + "[1]/" + CmsConfigurationReader.N_PAGE,
500                locale).setStringValue(m_cms, defaultModelTarget);
501            content.getValue(
502                CmsConfigurationReader.N_MODEL_PAGE + "[1]/" + CmsConfigurationReader.N_DISABLED,
503                locale).setStringValue(m_cms, Boolean.FALSE.toString());
504            content.getValue(
505                CmsConfigurationReader.N_MODEL_PAGE + "[1]/" + CmsConfigurationReader.N_IS_DEFAULT,
506                locale).setStringValue(m_cms, Boolean.TRUE.toString());
507        }
508        content.setAutoCorrectionEnabled(true);
509        content.correctXmlStructure(m_cms);
510        file.setContents(content.marshal());
511        m_cms.writeFile(file);
512        OpenCms.getADEManager().waitForCacheUpdate(false);
513        m_adeConfig = OpenCms.getADEManager().lookupConfiguration(m_cms, m_rootResource.getRootPath());
514        return getModelInfo();
515    }
516
517    /**
518     * Builds the model page list.<p>
519     *
520     * @param modelPageConfigs the model page configuration
521     *
522     * @return the list
523     */
524    private List<CmsModelPageEntry> buildModelPageList(List<CmsModelPageConfig> modelPageConfigs) {
525
526        List<CmsModelPageEntry> result = Lists.newArrayList();
527        Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms);
528        for (CmsModelPageConfig config : modelPageConfigs) {
529            CmsUUID structureId = config.getResource().getStructureId();
530            try {
531                CmsResource modelPage = m_cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
532                CmsModelPageEntry entry = createModelPageEntry(
533                    modelPage,
534                    config.isDisabled(),
535                    config.isDefault(),
536                    wpLocale);
537                if (entry != null) {
538                    result.add(entry);
539                }
540            } catch (CmsVfsResourceNotFoundException e) {
541                continue;
542            } catch (Exception e) {
543                LOG.error(e.getLocalizedMessage(), e);
544                continue;
545            }
546        }
547        return result;
548    }
549
550    /**
551     * Helper method for getting the locale from which to read the configuration data.<p>
552     *
553     * @param content the configuration content
554     *
555     * @return the locale from which to read the configuration data
556     */
557    private Locale getLocale(CmsXmlContent content) {
558
559        List<Locale> locales = content.getLocales();
560        if (locales.contains(Locale.ENGLISH) || locales.isEmpty()) {
561            return Locale.ENGLISH;
562        }
563        return locales.get(0);
564    }
565
566    /**
567     * Gets the type for a type name.<p>
568     *
569     * @param name the type name
570     * @return the type
571     * @throws CmsLoaderException if something goes wrong
572     */
573    private I_CmsResourceType getType(String name) throws CmsLoaderException {
574
575        return OpenCms.getResourceManager().getResourceType(name);
576    }
577
578    /**
579     * Tries to unlock a resource.<p>
580     *
581     * @param resource the resource to unlock
582     */
583    private void tryUnlock(CmsResource resource) {
584
585        try {
586            m_cms.unlockResource(resource);
587        } catch (Exception unlockError) {
588            LOG.debug(unlockError.getLocalizedMessage(), unlockError);
589        }
590    }
591
592    /**
593     * Writes a sitemap configuration back to the VFS.<p>
594     *
595     * @param content the content to write
596     * @param sitemapConfigFile the file to which the sitemap config should be written
597     *
598     * @throws CmsXmlException if an XML processing error occurs
599     * @throws CmsException if something goes wrong
600     */
601    private void writeSitemapConfig(CmsXmlContent content, CmsFile sitemapConfigFile)
602    throws CmsXmlException, CmsException {
603
604        content.correctXmlStructure(m_cms);
605        byte[] contentBytes = content.marshal();
606        sitemapConfigFile.setContents(contentBytes);
607        try {
608            CmsLock lock = m_cms.getLock(sitemapConfigFile);
609            if (lock.isUnlocked() || !lock.isOwnedBy(m_cms.getRequestContext().getCurrentUser())) {
610                m_cms.lockResourceTemporary(sitemapConfigFile);
611            }
612            m_cms.writeFile(sitemapConfigFile);
613        } finally {
614            m_cms.unlockResource(sitemapConfigFile);
615        }
616    }
617
618}