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