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.containerpage;
029
030import org.opencms.ade.configuration.CmsADEConfigData;
031import org.opencms.ade.configuration.CmsElementView;
032import org.opencms.ade.configuration.CmsResourceTypeConfig;
033import org.opencms.ade.containerpage.inherited.CmsContainerConfigurationCache;
034import org.opencms.ade.containerpage.inherited.CmsInheritanceReference;
035import org.opencms.ade.containerpage.inherited.CmsInheritanceReferenceParser;
036import org.opencms.ade.containerpage.inherited.CmsInheritedContainerState;
037import org.opencms.ade.containerpage.shared.CmsContainer;
038import org.opencms.ade.containerpage.shared.CmsContainerElement;
039import org.opencms.ade.containerpage.shared.CmsContainerElement.ModelGroupState;
040import org.opencms.ade.containerpage.shared.CmsContainerElementData;
041import org.opencms.ade.containerpage.shared.CmsElementLockInfo;
042import org.opencms.ade.containerpage.shared.CmsElementSettingsConfig;
043import org.opencms.ade.containerpage.shared.CmsFormatterConfig;
044import org.opencms.ade.containerpage.shared.CmsFormatterConfigCollection;
045import org.opencms.ade.containerpage.shared.CmsInheritanceInfo;
046import org.opencms.ade.detailpage.CmsDetailPageResourceHandler;
047import org.opencms.configuration.CmsConfigurationException;
048import org.opencms.db.CmsResourceState;
049import org.opencms.file.CmsFile;
050import org.opencms.file.CmsObject;
051import org.opencms.file.CmsRequestContext;
052import org.opencms.file.CmsResource;
053import org.opencms.file.CmsResourceFilter;
054import org.opencms.file.CmsUser;
055import org.opencms.file.types.CmsResourceTypeXmlContainerPage;
056import org.opencms.file.types.CmsResourceTypeXmlContent;
057import org.opencms.file.types.I_CmsResourceType;
058import org.opencms.gwt.CmsDefaultResourceStatusProvider;
059import org.opencms.gwt.CmsIconUtil;
060import org.opencms.gwt.shared.CmsAdditionalInfoBean;
061import org.opencms.gwt.shared.CmsPermissionInfo;
062import org.opencms.i18n.CmsMessageContainer;
063import org.opencms.i18n.CmsMessages;
064import org.opencms.jsp.util.CmsJspStandardContextBean;
065import org.opencms.jsp.util.CmsJspStandardContextBean.TemplateBean;
066import org.opencms.loader.CmsTemplateContextManager;
067import org.opencms.lock.CmsLock;
068import org.opencms.main.CmsException;
069import org.opencms.main.CmsLog;
070import org.opencms.main.OpenCms;
071import org.opencms.relations.CmsRelation;
072import org.opencms.relations.CmsRelationFilter;
073import org.opencms.relations.CmsRelationType;
074import org.opencms.search.galleries.CmsGallerySearch;
075import org.opencms.search.galleries.CmsGallerySearchResult;
076import org.opencms.util.CmsDateUtil;
077import org.opencms.util.CmsStringUtil;
078import org.opencms.util.CmsUUID;
079import org.opencms.workplace.CmsWorkplaceMessages;
080import org.opencms.workplace.editors.CmsWorkplaceEditorManager;
081import org.opencms.workplace.editors.directedit.CmsAdvancedDirectEditProvider;
082import org.opencms.workplace.editors.directedit.CmsDirectEditMode;
083import org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider;
084import org.opencms.workplace.explorer.CmsExplorerTypeSettings;
085import org.opencms.workplace.explorer.CmsResourceUtil;
086import org.opencms.xml.containerpage.CmsADESessionCache;
087import org.opencms.xml.containerpage.CmsContainerBean;
088import org.opencms.xml.containerpage.CmsContainerElementBean;
089import org.opencms.xml.containerpage.CmsContainerPageBean;
090import org.opencms.xml.containerpage.CmsFormatterConfiguration;
091import org.opencms.xml.containerpage.CmsGroupContainerBean;
092import org.opencms.xml.containerpage.CmsXmlContainerPage;
093import org.opencms.xml.containerpage.CmsXmlContainerPageFactory;
094import org.opencms.xml.containerpage.CmsXmlGroupContainer;
095import org.opencms.xml.containerpage.CmsXmlGroupContainerFactory;
096import org.opencms.xml.containerpage.I_CmsFormatterBean;
097import org.opencms.xml.content.CmsXmlContent;
098import org.opencms.xml.content.CmsXmlContentFactory;
099import org.opencms.xml.content.CmsXmlContentProperty;
100import org.opencms.xml.content.CmsXmlContentPropertyHelper;
101
102import java.io.IOException;
103import java.text.DateFormat;
104import java.util.ArrayList;
105import java.util.Collection;
106import java.util.Collections;
107import java.util.Date;
108import java.util.HashMap;
109import java.util.LinkedHashMap;
110import java.util.LinkedHashSet;
111import java.util.List;
112import java.util.Locale;
113import java.util.Map;
114import java.util.Map.Entry;
115import java.util.Set;
116import java.util.function.Function;
117import java.util.regex.Matcher;
118import java.util.regex.Pattern;
119
120import javax.servlet.ServletException;
121import javax.servlet.http.HttpServletRequest;
122import javax.servlet.http.HttpServletResponse;
123
124import org.apache.commons.logging.Log;
125
126import com.google.common.base.Supplier;
127import com.google.common.base.Suppliers;
128import com.google.common.collect.Sets;
129
130/**
131 * Utility class to generate the element data objects used within the container-page editor.<p>
132 *
133 * @since 8.0.0
134 */
135public class CmsElementUtil {
136
137    /** The maximum number of nested container levels. */
138    public static final int MAX_NESTING_LEVEL = 7;
139
140    /** Static reference to the log. */
141    private static final Log LOG = CmsLog.getLog(org.opencms.ade.containerpage.CmsElementUtil.class);
142
143    /** The ADE configuration data for the current page URI. */
144    private CmsADEConfigData m_adeConfig;
145
146    /** The cms context. */
147    private CmsObject m_cms;
148
149    /** The current page uri. */
150    private String m_currentPageUri;
151
152    /** The content locale. */
153    private Locale m_locale;
154
155    /** The current container page. */
156    private CmsResource m_page;
157
158    /** The request parameters to use while rendering the elements. */
159    @SuppressWarnings("unused")
160    private Map<String, Object> m_parameterMap;
161
162    /** The http request. */
163    private HttpServletRequest m_req;
164
165    /** The http response. */
166    private HttpServletResponse m_res;
167
168    /** The standard context bean. */
169    private CmsJspStandardContextBean m_standardContext;
170
171    /**
172     * Creates a new instance.<p>
173     * Use this constructor to set the current container page state.<p>
174     *
175     * @param cms the cms context
176     * @param currentPageUri the current page uri
177     * @param containerPage the container page bean with the current container state
178     * @param detailContentId the detail content structure id
179     * @param req the http request
180     * @param res the http response
181     * @param isDragMode if the page is in drag mode
182     * @param locale the content locale
183     *
184     * @throws CmsException if something goes wrong
185     */
186    public CmsElementUtil(
187        CmsObject cms,
188        String currentPageUri,
189        CmsContainerPageBean containerPage,
190        CmsUUID detailContentId,
191        HttpServletRequest req,
192        HttpServletResponse res,
193        boolean isDragMode,
194        Locale locale)
195    throws CmsException {
196
197        m_cms = OpenCms.initCmsObject(cms);
198        String contextPath = (String)cms.getRequestContext().getAttribute(CmsRequestContext.ATTRIBUTE_ADE_CONTEXT_PATH);
199        if (contextPath != null) {
200            m_cms.getRequestContext().setAttribute(CmsRequestContext.ATTRIBUTE_ADE_CONTEXT_PATH, contextPath);
201        }
202        m_req = req;
203        m_res = res;
204        m_currentPageUri = currentPageUri;
205        m_locale = locale;
206        // initializing request for standard context bean
207        req.setAttribute(CmsJspStandardContextBean.ATTRIBUTE_CMS_OBJECT, m_cms);
208        if (detailContentId != null) {
209            CmsResource detailRes = m_cms.readResource(
210                detailContentId,
211                CmsResourceFilter.ignoreExpirationOffline(m_cms));
212            req.setAttribute(CmsDetailPageResourceHandler.ATTR_DETAIL_CONTENT_RESOURCE, detailRes);
213        }
214        m_standardContext = CmsJspStandardContextBean.getInstance(req);
215        m_page = m_cms.readResource(currentPageUri, CmsResourceFilter.ignoreExpirationOffline(cms));
216        m_standardContext.setPage(containerPage);
217        m_standardContext.setDragMode(isDragMode);
218    }
219
220    /**
221     * Creates a new instance.<p>
222     *
223     * @param cms the cms context
224     * @param currentPageUri the current page uri
225     * @param detailContentId the detail content structure id
226     * @param req the http request
227     * @param res the http response
228     * @param locale the content locale
229     *
230     * @throws CmsException if something goes wrong
231     */
232    public CmsElementUtil(
233        CmsObject cms,
234        String currentPageUri,
235        CmsUUID detailContentId,
236        HttpServletRequest req,
237        HttpServletResponse res,
238        Locale locale)
239    throws CmsException {
240
241        m_cms = OpenCms.initCmsObject(cms);
242        m_req = req;
243        m_res = res;
244        m_currentPageUri = currentPageUri;
245        m_locale = locale;
246        // initializing request for standard context bean
247        req.setAttribute(CmsJspStandardContextBean.ATTRIBUTE_CMS_OBJECT, m_cms);
248        if (detailContentId != null) {
249            CmsResource detailRes = m_cms.readResource(detailContentId, CmsResourceFilter.ignoreExpirationOffline(cms));
250            req.setAttribute(CmsDetailPageResourceHandler.ATTR_DETAIL_CONTENT_RESOURCE, detailRes);
251        }
252        m_standardContext = CmsJspStandardContextBean.getInstance(req);
253        m_page = m_cms.readResource(currentPageUri);
254        CmsXmlContainerPage xmlContainerPage = CmsXmlContainerPageFactory.unmarshal(cms, m_page, req);
255        CmsContainerPageBean containerPage = xmlContainerPage.getContainerPage(cms);
256        m_standardContext.setPage(containerPage);
257    }
258
259    /**
260     * Creates a new instance.<p>
261     *
262     * @param cms the cms context
263     * @param currentPageUri the current page uri
264     * @param detailContentId the detail content structure id
265     * @param requestParameters the request parameters to use while rendering the elements
266     * @param req the http request
267     * @param res the http response
268     * @param locale the content locale
269     *
270     * @throws CmsException if something goes wrong
271     */
272    public CmsElementUtil(
273        CmsObject cms,
274        String currentPageUri,
275        CmsUUID detailContentId,
276        String requestParameters,
277        HttpServletRequest req,
278        HttpServletResponse res,
279        Locale locale)
280    throws CmsException {
281
282        this(cms, currentPageUri, detailContentId, req, res, locale);
283        m_parameterMap = parseRequestParameters(requestParameters);
284    }
285
286    /**
287     * Checks if a group element is allowed in a container with a given type.<p>
288     *
289     * @param containerType the container type spec (comma separated)
290     * @param groupContainer the group
291     *
292     * @return true if the group is allowed in the container
293     */
294    public static boolean checkGroupAllowed(String containerType, CmsGroupContainerBean groupContainer) {
295
296        return !Sets.intersection(CmsContainer.splitType(containerType), groupContainer.getTypes()).isEmpty();
297    }
298
299    public static CmsContainerBean clientToServerContainer(
300        CmsContainer container,
301        List<CmsContainerElementBean> elements) {
302
303        return new CmsContainerBean(
304            container.getName(),
305            container.getType(),
306            container.getParentInstanceId(),
307            container.isRootContainer(),
308            container.getMaxElements(),
309            elements);
310
311    }
312
313    /**
314     * Helper method to create a string template source for a given formatter and content.
315     *
316     * @param formatter the formatter
317     * @param contentSupplier the content supplier
318     *
319     * @return the string template provider
320     */
321    public static Function<String, String> createStringTemplateSource(
322        I_CmsFormatterBean formatter,
323        Supplier<CmsXmlContent> contentSupplier) {
324
325        return key -> {
326            String result = null;
327            if (formatter != null) {
328                result = formatter.getAttributes().get(key);
329            }
330            if (result == null) {
331                CmsXmlContent content = contentSupplier.get();
332                if (content != null) {
333                    result = content.getHandler().getParameter(key);
334                }
335            }
336            return result;
337        };
338    }
339
340    /**
341     * Returns the formatter bean for the given element and container.<p>
342     *
343     * @param cms the cms context
344     * @param element the element to render
345     * @param container the container
346     * @param config the configuration data
347     * @param cache the session cache
348     *
349     * @return the formatter bean
350     */
351    public static I_CmsFormatterBean getFormatterForContainer(
352        CmsObject cms,
353        CmsContainerElementBean element,
354        CmsContainer container,
355        CmsADEConfigData config,
356        CmsADESessionCache cache) {
357
358        I_CmsFormatterBean formatter = null;
359        CmsFormatterConfiguration formatterSet = config.getFormatters(cms, element.getResource());
360        Map<String, I_CmsFormatterBean> formatters = formatterSet.getFormatterSelectionByKeyOrId(
361            container.getType(),
362            container.getWidth());
363        String formatterId = element.getIndividualSettings().get(
364            CmsFormatterConfig.getSettingsKeyForContainer(container.getName()));
365        if (formatterId != null) {
366            I_CmsFormatterBean dynamicFmt = config.findFormatter(formatterId);
367            if (dynamicFmt != null) {
368                formatter = dynamicFmt;
369            } else {
370                formatter = formatters.get(formatterId);
371            }
372        }
373        if (formatter == null) {
374            formatterId = element.getIndividualSettings().get(CmsFormatterConfig.FORMATTER_SETTINGS_KEY);
375            if (formatterId != null) {
376                formatter = lookupFormatter(config, formatterId, formatters);
377            }
378        }
379        if (formatter == null) {
380            // check for formatter config id stored for other containers matching the current container
381            for (Entry<String, String> settingsEntry : element.getIndividualSettings().entrySet()) {
382                if (settingsEntry.getKey().startsWith(CmsFormatterConfig.FORMATTER_SETTINGS_KEY)) {
383                    formatter = lookupFormatter(config, settingsEntry.getValue(), formatters);
384                    if (formatter != null) {
385                        break;
386                    }
387                }
388            }
389        }
390        if ((formatter == null) && (element.getFormatterId() != null)) {
391            for (I_CmsFormatterBean currentFormatter : formatters.values()) {
392                if ((currentFormatter.getJspStructureId() != null)
393                    && currentFormatter.getJspStructureId().equals(element.getFormatterId())) {
394                    formatter = currentFormatter;
395                    break;
396                }
397            }
398        }
399        if (formatter == null) {
400            formatter = getStartFormatter(cms, container, config, element, cache);
401        }
402        return formatter;
403    }
404
405    /**
406     * Checks if the given setting name is a system setting.
407     *
408     * @param name the setting name
409     * @return true if the name corresponds to a system setting
410     */
411    public static final boolean isSystemSetting(String name) {
412
413        if (CmsXmlContainerPage.LEGACY_SYSTEM_SETTING_NAMES.contains(name)
414            || CmsContainerElement.ELEMENT_INSTANCE_ID.equals(name)
415            || name.startsWith(CmsXmlContainerPage.SYSTEM_SETTING_PREFIX)
416            || name.startsWith(CmsFormatterConfig.FORMATTER_SETTINGS_KEY)) {
417            return true;
418        }
419        return false;
420    }
421
422    /**
423     * Returns the start formatter for a newly dropped element.<p>
424     * This will be either the least recently used matching formatter or the default formatter.<p>
425     *
426     * @param cms the cms context
427     * @param cnt the container
428     * @param configData the configuration data
429     * @param element the container element
430     * @param cache the session cache
431     *
432     * @return the formatter bean
433     */
434    private static I_CmsFormatterBean getStartFormatter(
435        CmsObject cms,
436        CmsContainer cnt,
437        CmsADEConfigData configData,
438        CmsContainerElementBean element,
439        CmsADESessionCache cache) {
440
441        I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(element.getResource());
442        I_CmsFormatterBean formatter = cache.getRecentFormatter(type.getTypeName(), cnt, configData);
443        if (formatter == null) {
444            formatter = configData.getFormatters(cms, element.getResource()).getDefaultFormatter(
445                cnt.getType(),
446                cnt.getWidth());
447        }
448        return formatter;
449    }
450
451    /**
452     * Helper method for looking up the correct formatter for an element.
453     *
454     * @param config the sitemap config
455     * @param keyOrId the key or id of the formatter stored with the container element
456     * @param active map of active formatters by key or id
457     *
458     * @return the formatter with the given key or id
459     */
460    private static I_CmsFormatterBean lookupFormatter(
461        CmsADEConfigData config,
462        String keyOrId,
463        Map<String, I_CmsFormatterBean> active) {
464
465        I_CmsFormatterBean dynamicFmt = config.findFormatter(keyOrId);
466        if (dynamicFmt != null) {
467            for (String key : new String[] {dynamicFmt.getKey(), dynamicFmt.getId(), keyOrId}) {
468                if ((key != null) && (active.get(key) != null)) {
469                    return active.get(key);
470                }
471            }
472            return null;
473        } else {
474            // schema formatters
475            return active.get(keyOrId);
476        }
477    }
478
479    /**
480     * Returns the HTML content for the given resource and container.<p>
481     *
482     * @param elementFile the element resource file
483     * @param elementId the element id
484     * @param container the container
485     *
486     * @return the HTML content
487     */
488    public String getContentByContainer(CmsFile elementFile, String elementId, CmsContainer container) {
489
490        CmsContainerElementBean element = CmsADESessionCache.getCache(m_req, m_cms).getCacheContainerElement(elementId);
491        element = element.clone();
492        element.setTemporaryFile(elementFile);
493        CmsFormatterConfiguration configs = getFormatterConfiguration(element.getResource());
494        return getContentByContainer(element, container, configs);
495    }
496
497    /**
498     * Returns the data for an element.<p>
499     *
500     * @param page the current container page
501     * @param element the resource
502     * @param containers the containers on the current container page
503     *
504     * @return the data for an element
505     *
506     * @throws CmsException if something goes wrong
507     */
508    public CmsContainerElementData getElementData(
509        CmsResource page,
510        CmsContainerElementBean element,
511        Collection<CmsContainer> containers)
512    throws CmsException {
513
514        Locale requestLocale = m_cms.getRequestContext().getLocale();
515        m_cms.getRequestContext().setLocale(m_locale);
516        element.initResource(m_cms);
517        if (element.getResource().isFolder()) {
518            return null;
519        }
520        boolean typeDisabled = false;
521        boolean createDisabled = false;
522        if (page != null) {
523
524            CmsADEConfigData config = OpenCms.getADEManager().lookupConfigurationWithCache(m_cms, page.getRootPath());
525            String typeName = OpenCms.getResourceManager().getResourceType(element.getResource()).getTypeName();
526            if (!config.getAddableTypeNames().contains(typeName)) {
527                typeDisabled = true;
528            }
529            CmsResourceTypeConfig typeConfig = config.getTypesByName().get(typeName);
530            if ((typeConfig == null) || typeConfig.isCreateDisabled()) {
531                createDisabled = true;
532            }
533        }
534
535        CmsContainerElementData elementData = getBaseElementData(page, element);
536        elementData.setAddDisabled(typeDisabled);
537        elementData.setCopyDisabled(createDisabled);
538        CmsFormatterConfiguration formatterConfiguraton = getFormatterConfiguration(element.getResource());
539        Map<String, String> contents = new HashMap<String, String>();
540        if (element.isGroupContainer(m_cms)) {
541            Map<String, CmsContainer> containersByName = new HashMap<String, CmsContainer>();
542            for (CmsContainer container : containers) {
543                containersByName.put(container.getName(), container);
544            }
545            CmsXmlGroupContainer xmlGroupContainer = CmsXmlGroupContainerFactory.unmarshal(
546                m_cms,
547                element.getResource(),
548                m_req);
549            CmsGroupContainerBean groupContainer = xmlGroupContainer.getGroupContainer(m_cms);
550            // make sure to use the content title and not the property title
551            elementData.setTitle(groupContainer.getTitle());
552            elementData.setTypes(groupContainer.getTypes());
553            elementData.setDescription(groupContainer.getDescription());
554            if (groupContainer.getTypes().isEmpty()) {
555                if (groupContainer.getElements().isEmpty()) {
556                    String emptySub = "<div>NEW AND EMPTY</div>";
557                    for (CmsContainer cont : containersByName.values()) {
558                        if (formatterConfiguraton.hasFormatter(cont.getType(), cont.getWidth())) {
559                            contents.put(cont.getName(), emptySub);
560                        }
561                    }
562                } else {
563                    // TODO: throw appropriate exception
564                    return null;
565                }
566            } else {
567
568                // add formatter and content entries for the supported types
569                for (CmsContainer cnt : containersByName.values()) {
570
571                    String type = cnt.getType();
572                    if (checkGroupAllowed(type, groupContainer)) {
573                        contents.put(cnt.getName(), "<div>should not be used</div>");
574                    }
575                }
576            }
577            // add subitems
578            List<String> subItems = new ArrayList<String>();
579
580            for (CmsContainerElementBean subElement : groupContainer.getElements()) {
581                // collect ids
582                subItems.add(subElement.editorHash());
583            }
584            elementData.setSubItems(subItems);
585        } else if (element.isInheritedContainer(m_cms)) {
586            CmsInheritanceReferenceParser parser = new CmsInheritanceReferenceParser(m_cms);
587            parser.parse(element.getResource());
588            CmsInheritanceReference ref = parser.getReference(m_locale);
589            String name = null;
590            // check for new inheritance reference
591            if (ref != null) {
592                name = ref.getName();
593                elementData.setDescription(ref.getDescription());
594                elementData.setTitle(ref.getTitle());
595            }
596            for (CmsContainer container : containers) {
597                if (formatterConfiguraton.hasFormatter(container.getType(), container.getWidth())) {
598                    contents.put(container.getName(), "<div>should not be used</div>");
599                }
600            }
601
602            List<CmsInheritanceInfo> inheritanceInfos = new ArrayList<CmsInheritanceInfo>();
603            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(name)) {
604                CmsInheritedContainerState result = OpenCms.getADEManager().getInheritedContainerState(
605                    m_cms,
606                    m_cms.addSiteRoot(m_currentPageUri),
607                    name);
608                for (CmsContainerElementBean subElement : result.getElements(true)) {
609                    CmsInheritanceInfo inheritanceInfo = subElement.getInheritanceInfo();
610                    inheritanceInfo.setClientId(subElement.editorHash());
611                    inheritanceInfos.add(inheritanceInfo);
612                }
613            } else {
614                // setting a new id for name, will be persisted once the inheritance reference is edited and saved.
615                // use the structure id so it will always be the same for the resource
616                name = element.getResource().getStructureId().toString();
617            }
618            elementData.setInheritanceInfos(inheritanceInfos);
619            elementData.setInheritanceName(name);
620        } else {
621
622            for (CmsContainer cnt : containers) {
623                boolean missesFormatterSetting = !elementData.getSettings().containsKey(
624                    CmsFormatterConfig.getSettingsKeyForContainer(cnt.getName()));
625                if (missesFormatterSetting) {
626                    if (element.getFormatterId() == null) {
627                        I_CmsFormatterBean formatter = getStartFormatter(
628                            m_cms,
629                            cnt,
630                            m_adeConfig,
631                            element,
632                            CmsADESessionCache.getCache(m_req, m_cms));
633                        if (formatter != null) {
634                            elementData.getSettings().put(
635                                CmsFormatterConfig.getSettingsKeyForContainer(cnt.getName()),
636                                formatter.getId());
637                            element.addFormatterSetting(cnt.getName(), formatter.getKeyOrId());
638                        }
639                    } else {
640                        Map<String, I_CmsFormatterBean> formatterSelection = formatterConfiguraton.getFormatterSelection(
641                            cnt.getType(),
642                            cnt.getWidth());
643                        for (Entry<String, I_CmsFormatterBean> formatterEntry : formatterSelection.entrySet()) {
644                            I_CmsFormatterBean formatter = formatterEntry.getValue();
645                            String id = formatterEntry.getKey();
646                            if (element.getFormatterId().equals(formatter.getJspStructureId())) {
647                                elementData.getSettings().put(
648                                    CmsFormatterConfig.getSettingsKeyForContainer(cnt.getName()),
649                                    formatter.getKeyOrId());
650                                break;
651                            }
652                        }
653                    }
654                }
655            }
656            // get the formatter configuration
657            Map<String, String> contentsByName = getContentsByContainerName(element, containers);
658            contents = contentsByName;
659        }
660        elementData.setContents(contents);
661        m_cms.getRequestContext().setLocale(requestLocale);
662        return elementData;
663    }
664
665    /**
666     * Returns the formatter and settings config data for an element.<p>
667     *
668     * @param page the current container page
669     * @param element the resource
670     * @param containerId the parent container id
671     * @param containers the containers on the current container page
672     *
673     * @return the data for an element
674     *
675     * @throws CmsException if something goes wrong
676     */
677    public CmsElementSettingsConfig getElementSettingsConfig(
678        CmsResource page,
679        CmsContainerElementBean element,
680        String containerId,
681        Collection<CmsContainer> containers)
682    throws CmsException {
683
684        Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms);
685        CmsADEConfigData adeConfig = OpenCms.getADEManager().lookupConfigurationWithCache(m_cms, page.getRootPath());
686        Locale requestLocale = m_cms.getRequestContext().getLocale();
687        m_cms.getRequestContext().setLocale(m_locale);
688        element.initResource(m_cms);
689        if (element.getResource().isFolder()) {
690            return null;
691        }
692        String schema = null;
693        try {
694            I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(element.getResource());
695            schema = type.getConfiguration().getString("schema", null);
696        } catch (Exception e) {
697            LOG.error(e.getLocalizedMessage(), e);
698        }
699        CmsContainerElementData elementData = getBaseElementData(page, element);
700
701        Map<String, String> settingUpdates = new HashMap<>();
702        for (Map.Entry<String, String> entry : elementData.getSettings().entrySet()) {
703            int underscorePos = entry.getKey().indexOf("_");
704            if ((underscorePos >= 0) && !isSystemSetting(entry.getKey())) {
705                String prefix = entry.getKey().substring(0, underscorePos);
706                I_CmsFormatterBean dynamicFmt = adeConfig.findFormatter(prefix, true);
707
708                if (CmsUUID.isValidUUID(prefix)) {
709                    // If we already have a formatter referenced by name, we don't need to do anything
710                    if ((dynamicFmt != null) && (dynamicFmt.getKey() != null)) {
711                        // Replace setting prefix with formatter key
712                        String newSettingName = dynamicFmt.getKey() + entry.getKey().substring(underscorePos);
713                        settingUpdates.put(newSettingName, entry.getValue());
714                        settingUpdates.put(entry.getKey(), null);
715                    }
716                }
717            }
718
719            if (entry.getKey().startsWith(CmsFormatterConfig.FORMATTER_SETTINGS_KEY)) {
720                String value = entry.getValue();
721                if (CmsUUID.isValidUUID(value)) {
722                    I_CmsFormatterBean dynamicFmt = adeConfig.findFormatter(value);
723                    if ((dynamicFmt != null) && (dynamicFmt.getKey() != null)) {
724                        settingUpdates.put(entry.getKey(), dynamicFmt.getKey());
725                    }
726                }
727            }
728        }
729        for (String key : settingUpdates.keySet()) {
730            String value = settingUpdates.get(key);
731            if (value == null) {
732                elementData.getSettings().remove(key);
733            } else {
734                elementData.getSettings().put(key, value);
735            }
736        }
737        Supplier<CmsXmlContent> contentSupplier = Suppliers.memoize(() -> {
738            try {
739                return CmsXmlContentFactory.unmarshal(m_cms, m_cms.readFile(element.getResource()));
740            } catch (CmsException e) {
741                LOG.error(e.getLocalizedMessage(), e);
742                return null;
743            }
744        });
745        I_CmsFormatterBean foundFormatter = null;
746
747        if (!element.isGroupContainer(m_cms) && !element.isInheritedContainer(m_cms)) {
748            CmsFormatterConfiguration formatterConfiguraton = getFormatterConfiguration(element.getResource());
749            Map<String, CmsFormatterConfigCollection> formatters = new HashMap<String, CmsFormatterConfigCollection>();
750            for (CmsContainer cnt : containers) {
751                if (cnt.getName().equals(containerId)) {
752                    CmsFormatterConfigCollection containerFormatters = new CmsFormatterConfigCollection();
753                    String foundFormatterKey = null;
754                    for (String containerName : new String[] {cnt.getName(), ""}) {
755                        foundFormatterKey = elementData.getSettings().get(
756                            CmsFormatterConfig.getSettingsKeyForContainer(containerName));
757                        if (foundFormatterKey != null) {
758                            break;
759                        }
760                    }
761                    boolean missesFormatterSetting = (foundFormatterKey == null);
762                    if (!missesFormatterSetting) {
763                        foundFormatter = adeConfig.findFormatter(foundFormatterKey);
764                    }
765                    Map<String, I_CmsFormatterBean> formatterSelection = formatterConfiguraton.getFormatterSelection(
766                        cnt.getType(),
767                        cnt.getWidth());
768                    for (Entry<String, I_CmsFormatterBean> formatterEntry : formatterSelection.entrySet()) {
769                        I_CmsFormatterBean formatter = formatterEntry.getValue();
770                        String id = formatterEntry.getValue().getId();
771                        if (missesFormatterSetting
772                            && ((element.getFormatterId() == null)
773                                || element.getFormatterId().equals(formatter.getJspStructureId()))) {
774                            elementData.getSettings().put(
775                                CmsFormatterConfig.getSettingsKeyForContainer(cnt.getName()),
776                                id);
777                            missesFormatterSetting = false;
778                        }
779                        String label = formatter.getNiceName(OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms));
780                        if (formatterEntry.getKey().startsWith(CmsFormatterConfig.SCHEMA_FORMATTER_ID)) {
781                            label = Messages.get().getBundle().key(Messages.GUI_SCHEMA_FORMATTER_LABEL_0)
782                                + " ["
783                                + CmsResource.getName(formatter.getJspRootPath())
784                                + "]";
785                        }
786                        if (CmsStringUtil.isEmptyOrWhitespaceOnly(label)) {
787                            label = id;
788                        }
789                        CmsFormatterConfig config = new CmsFormatterConfig(id);
790                        Set<String> cssResources = new LinkedHashSet<String>();
791                        for (String cssSitePath : formatter.getCssHeadIncludes()) {
792                            cssResources.add(OpenCms.getLinkManager().getOnlineLink(m_cms, cssSitePath));
793                        }
794                        config.setCssResources(cssResources);
795                        config.setInlineCss(formatter.getInlineCss());
796                        config.setKey(formatter.getKey());
797                        config.setLabel(label);
798                        config.setDescription(
799                            formatter.getDescription(OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms)));
800                        Map<String, CmsXmlContentProperty> settingsConfig = OpenCms.getADEManager().getFormatterSettings(
801                            m_cms,
802                            adeConfig,
803                            formatter,
804                            element.getResource(),
805                            m_locale,
806                            m_req);
807                        Function<String, String> templateSource = createStringTemplateSource(
808                            formatter,
809                            contentSupplier);
810                        settingsConfig = CmsXmlContentPropertyHelper.resolveMacrosForPropertyInfo(
811                            m_cms,
812                            page,
813                            element.getResource(),
814                            contentSupplier,
815                            templateSource,
816                            settingsConfig);
817                        config.setSettingConfig(settingsConfig);
818                        List<I_CmsFormatterBean> nestedFormatters = OpenCms.getADEManager().getNestedFormatters(
819                            m_cms,
820                            adeConfig,
821                            element.getResource(),
822                            m_locale,
823                            m_req);
824                        if ((nestedFormatters != null) && !nestedFormatters.isEmpty()) {
825                            Map<String, String> settingPrefixes = new LinkedHashMap<String, String>();
826                            for (I_CmsFormatterBean nested : nestedFormatters) {
827                                String sectionLabel = nested.getNiceName(
828                                    OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms));
829                                settingPrefixes.put(nested.getId(), sectionLabel);
830                                if (nested.getKey() != null) {
831                                    settingPrefixes.put(nested.getKey() + "_", sectionLabel);
832                                }
833                            }
834                            config.setNestedFormatterPrefixes(settingPrefixes);
835                        }
836
837                        config.setJspRootPath(formatter.getJspRootPath());
838                        containerFormatters.add(config);
839                    }
840                    formatters.put(cnt.getName(), containerFormatters);
841                }
842            }
843            elementData.setFormatters(formatters);
844        }
845
846        m_cms.getRequestContext().setLocale(requestLocale);
847        ArrayList<CmsAdditionalInfoBean> infos = new ArrayList<>();
848
849        CmsResource resource = element.getResource();
850        String resTypeName = OpenCms.getResourceManager().getResourceType(resource).getTypeName();
851        CmsExplorerTypeSettings cmsExplorerTypeSettings = OpenCms.getWorkplaceManager().getExplorerTypeSetting(
852            resTypeName);
853        if (null == cmsExplorerTypeSettings) {
854            CmsMessageContainer errMsg = org.opencms.gwt.Messages.get().container(
855                org.opencms.gwt.Messages.ERR_EXPLORER_TYPE_SETTINGS_FOR_RESOURCE_TYPE_NOT_FOUND_3,
856                resource.getRootPath(),
857                resTypeName,
858                Integer.valueOf(resource.getTypeId()));
859            throw new CmsConfigurationException(errMsg);
860        }
861        String key = cmsExplorerTypeSettings.getKey();
862        Locale currentLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms);
863        CmsMessages messages = OpenCms.getWorkplaceManager().getMessages(currentLocale);
864        String resTypeNiceName = messages.key(key);
865        infos.add(
866            new CmsAdditionalInfoBean(
867                messages.key(org.opencms.workplace.commons.Messages.GUI_LABEL_TYPE_0),
868                resTypeNiceName,
869                null));
870
871        try {
872            CmsRelationFilter filter = CmsRelationFilter.relationsFromStructureId(
873                element.getResource().getStructureId()).filterType(CmsRelationType.XSD);
874            for (CmsRelation relation : m_cms.readRelations(filter)) {
875                CmsResource target = relation.getTarget(m_cms, CmsResourceFilter.IGNORE_EXPIRATION);
876                String label = Messages.get().getBundle(wpLocale).key(Messages.GUI_ADDINFO_SCHEMA_0);
877                infos.add(new CmsAdditionalInfoBean(label, target.getRootPath(), null));
878                break;
879            }
880        } catch (CmsException e) {
881            LOG.error(e.getLocalizedMessage(), e);
882        }
883        if (foundFormatter != null) {
884            Map<String, String> formatterInfo = CmsDefaultResourceStatusProvider.getFormatterInfo(
885                m_cms,
886                foundFormatter);
887            for (Map.Entry<String, String> entry : formatterInfo.entrySet()) {
888                infos.add(new CmsAdditionalInfoBean(entry.getKey(), entry.getValue(), null));
889            }
890        }
891
892        CmsResourceState state = element.getResource().getState();
893        return new CmsElementSettingsConfig(elementData, state, infos, schema);
894    }
895
896    /**
897     * Gets the container page.<p>
898     *
899     * @return the container page resource
900     */
901    public CmsResource getPage() {
902
903        return m_page;
904    }
905
906    /**
907     * Sets the data to the given container element.<p>
908     *
909     * @param elementBean the element bean
910     * @param result the container element to set the data to
911     *
912     * @return the container element
913     *
914     * @throws CmsException if something goes wrong
915     */
916    public CmsContainerElement setElementInfo(CmsContainerElementBean elementBean, CmsContainerElement result)
917    throws CmsException {
918
919        Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(m_cms);
920        // reinitializing resource to avoid caching issues
921        elementBean.initResource(m_cms);
922        CmsResource resource = elementBean.getResource();
923        boolean isModelGroup = elementBean.getIndividualSettings().containsKey(CmsContainerElement.MODEL_GROUP_ID);
924        if (isModelGroup) {
925            CmsUUID groupId = new CmsUUID(elementBean.getIndividualSettings().get(CmsContainerElement.MODEL_GROUP_ID));
926            resource = m_cms.readResource(groupId, CmsResourceFilter.IGNORE_EXPIRATION);
927        }
928
929        boolean newEditorDisabled = !CmsWorkplaceEditorManager.checkAcaciaEditorAvailable(
930            m_cms,
931            elementBean.getResource());
932        result.setNewEditorDisabled(newEditorDisabled);
933        I_CmsResourceType resourceType = OpenCms.getResourceManager().getResourceType(resource);
934        String typeName = resourceType.getTypeName();
935        result.setHasEditHandler(
936            (resourceType instanceof CmsResourceTypeXmlContent)
937                && (((CmsResourceTypeXmlContent)resourceType).getEditHandler(m_cms) != null));
938        result.setResourceType(typeName);
939        result.setIconClasses(
940            CmsIconUtil.getIconClasses(
941                CmsIconUtil.getDisplayType(m_cms, resource),
942                elementBean.getResource().getName(),
943                false));
944        CmsPermissionInfo permissionInfo;
945        String title;
946        String subTitle;
947        if (!elementBean.isInMemoryOnly()) {
948            CmsElementLockInfo lockInfo = getLockInfo(m_cms, resource);
949            result.setLockInfo(lockInfo);
950            permissionInfo = OpenCms.getADEManager().getPermissionInfo(m_cms, resource, m_page.getRootPath());
951            if (CmsResourceTypeXmlContent.isXmlContent(resource)) {
952                if (CmsStringUtil.isEmptyOrWhitespaceOnly(permissionInfo.getNoEditReason())
953                    && elementBean.isInheritedContainer(m_cms)) {
954                    String requestUri = m_cms.getRequestContext().getUri();
955                    String folderPath = CmsResource.getFolderPath(requestUri);
956                    String configPath = CmsStringUtil.joinPaths(
957                        folderPath,
958                        CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME);
959                    if (m_cms.existsResource(configPath)) {
960                        permissionInfo.setNoEditReason(
961                            new CmsResourceUtil(m_cms, m_cms.readResource(configPath)).getNoEditReason(wpLocale, true));
962                    } else {
963                        if (!m_cms.getLock(folderPath).isLockableBy(m_cms.getRequestContext().getCurrentUser())) {
964                            permissionInfo.setNoEditReason(
965                                org.opencms.workplace.explorer.Messages.get().getBundle(wpLocale).key(
966                                    org.opencms.workplace.explorer.Messages.GUI_NO_EDIT_REASON_LOCK_1,
967                                    new CmsResourceUtil(m_cms, m_cms.readResource(folderPath)).getLockedByName()));
968                        }
969                    }
970                }
971            } else {
972                permissionInfo.setNoEditReason(
973                    Messages.get().getBundle(wpLocale).key(Messages.GUI_ELEMENT_RESOURCE_CAN_NOT_BE_EDITED_0));
974            }
975            CmsGallerySearchResult searchResult = CmsGallerySearch.searchById(
976                m_cms,
977                resource.getStructureId(),
978                m_locale);
979            title = searchResult.getTitle();
980            if (CmsStringUtil.isEmptyOrWhitespaceOnly(title)) {
981                resource.getName();
982            }
983            subTitle = searchResult.getUserLastModified();
984            Date lastModDate = searchResult.getDateLastModified();
985            if (lastModDate != null) {
986                subTitle += " / " + CmsDateUtil.getDateTime(lastModDate, DateFormat.MEDIUM, wpLocale);
987            }
988        } else {
989            permissionInfo = new CmsPermissionInfo(true, true, "");
990            title = CmsWorkplaceMessages.getResourceTypeName(wpLocale, typeName);
991            subTitle = CmsWorkplaceMessages.getResourceTypeDescription(wpLocale, typeName);
992        }
993        result.setTitle(title);
994        result.setSubTitle(subTitle);
995        result.setClientId(elementBean.editorHash());
996        result.setSitePath(m_cms.getSitePath(resource));
997
998        result.setCreateNew(elementBean.isCreateNew());
999        CmsResourceTypeConfig typeConfig = getConfigData().getResourceType(typeName);
1000        if (typeConfig != null) {
1001            result.setCopyInModels(typeConfig.isCopyInModels());
1002        }
1003        Map<CmsUUID, CmsElementView> viewMap = OpenCms.getADEManager().getElementViews(m_cms);
1004
1005        boolean isModelGroupEditing = CmsModelGroupHelper.isModelGroupResource(m_page);
1006        if (!isModelGroup
1007            && isModelGroupEditing
1008            && elementBean.getIndividualSettings().containsKey(CmsContainerElement.MODEL_GROUP_STATE)
1009            && (ModelGroupState.isModelGroup == ModelGroupState.evaluate(
1010                elementBean.getIndividualSettings().get(CmsContainerElement.MODEL_GROUP_STATE)))) {
1011            isModelGroup = true;
1012        }
1013        if (!isModelGroupEditing && isModelGroup) {
1014            CmsResourceTypeConfig modelGroupConfig = getConfigData().getResourceType(
1015                CmsResourceTypeXmlContainerPage.MODEL_GROUP_TYPE_NAME);
1016            if (modelGroupConfig != null) {
1017                CmsUUID elementView = modelGroupConfig.getElementView();
1018                CmsElementView viewObject = viewMap.get(elementView);
1019                if ((viewObject != null) && (viewObject.getParentViewId() != null)) {
1020                    elementView = viewObject.getParentViewId();
1021                }
1022                result.setElementView(elementView);
1023            }
1024        } else if (typeConfig != null) {
1025            CmsUUID elementView = typeConfig.getElementView();
1026            CmsElementView viewObject = viewMap.get(elementView);
1027            if ((viewObject != null) && (viewObject.getParentViewId() != null)) {
1028                elementView = viewObject.getParentViewId();
1029            }
1030            result.setElementView(elementView);
1031        }
1032        if (CmsStringUtil.isEmptyOrWhitespaceOnly(permissionInfo.getNoEditReason())
1033            && ((typeConfig == null) || typeConfig.isEditDisabled())) {
1034            String message = Messages.get().getBundle(wpLocale).key(
1035                Messages.GUI_CONTAINERPAGE_EDIT_DISABLED_BY_SITEMAP_CONFIG_0);
1036            permissionInfo.setNoEditReason(message);
1037        }
1038        result.setHasSettings(hasSettings(m_cms, elementBean.getResource()));
1039        result.setPermissionInfo(permissionInfo);
1040        result.setReleasedAndNotExpired(elementBean.isReleasedAndNotExpired());
1041        if (elementBean.isModelGroup()) {
1042            String modelId = elementBean.getIndividualSettings().get(CmsContainerElement.MODEL_GROUP_ID);
1043            result.setModelGroupId(modelId != null ? new CmsUUID(modelId) : CmsUUID.getNullUUID());
1044        }
1045        result.setWasModelGroup(
1046            elementBean.getIndividualSettings().containsKey(CmsContainerElement.MODEL_GROUP_STATE)
1047                && (ModelGroupState.evaluate(
1048                    elementBean.getIndividualSettings().get(
1049                        CmsContainerElement.MODEL_GROUP_STATE)) == ModelGroupState.wasModelGroup));
1050        return result;
1051    }
1052
1053    /**
1054     * Returns the formatter configuration for the given element resource.<p>
1055     *
1056     * @param resource the element resource
1057     *
1058     * @return the formatter configuration
1059     */
1060    CmsFormatterConfiguration getFormatterConfiguration(CmsResource resource) {
1061
1062        return getConfigData().getFormatters(m_cms, resource);
1063    }
1064
1065    /**
1066     * Returns the base element data for the given element bean, without content or formatter info.<p>
1067     *
1068     * @param page the current container page
1069     * @param element the resource
1070     *
1071     * @return base element data
1072     *
1073     * @throws CmsException in case reading the data fails
1074     */
1075    private CmsContainerElementData getBaseElementData(CmsResource page, CmsContainerElementBean element)
1076    throws CmsException {
1077
1078        CmsResourceUtil resUtil = new CmsResourceUtil(m_cms, element.getResource());
1079        CmsContainerElementData elementData = new CmsContainerElementData();
1080        setElementInfo(element, elementData);
1081        elementData.setLoadTime(System.currentTimeMillis());
1082        elementData.setLastModifiedDate(element.getResource().getDateLastModified());
1083        String userName = null;
1084        try {
1085            CmsUser user = m_cms.readUser(element.getResource().getUserLastModified());
1086            userName = user.getName();
1087        } catch (CmsException e) {
1088            userName = "" + element.getResource().getUserLastModified();
1089            LOG.debug(e.getLocalizedMessage(), e);
1090        }
1091        elementData.setLastModifiedByUser(userName);
1092        elementData.setNavText(resUtil.getNavText());
1093        Map<String, CmsXmlContentProperty> settingConfig = CmsXmlContentPropertyHelper.getPropertyInfo(
1094            m_cms,
1095            page,
1096            element.getResource());
1097        elementData.setSettings(
1098            CmsXmlContentPropertyHelper.convertPropertiesToClientFormat(
1099                m_cms,
1100                element.getIndividualSettings(),
1101                settingConfig));
1102        return elementData;
1103    }
1104
1105    /**
1106     * Returns the ADE configuration data for the current URI.<p>
1107     *
1108     * @return the ADE configuration data
1109     */
1110    private CmsADEConfigData getConfigData() {
1111
1112        if (m_adeConfig == null) {
1113            m_adeConfig = OpenCms.getADEManager().lookupConfigurationWithCache(
1114                m_cms,
1115                m_cms.addSiteRoot(m_currentPageUri));
1116        }
1117        return m_adeConfig;
1118    }
1119
1120    /**
1121     * Returns the HTML content of the given element and container.<p>
1122     *
1123     * @param element the element
1124     * @param container the container
1125     * @param configs the formatter configurations
1126     *
1127     * @return the HTML content
1128     */
1129    private String getContentByContainer(
1130        CmsContainerElementBean element,
1131        CmsContainer container,
1132        CmsFormatterConfiguration configs) {
1133
1134        String content = null;
1135
1136        I_CmsFormatterBean formatter = getFormatterForContainer(
1137            m_cms,
1138            element,
1139            container,
1140            m_adeConfig,
1141            CmsADESessionCache.getCache(m_req, m_cms));
1142        if (formatter != null) {
1143            element = element.clone(); // clone element because presets for different containers may be different
1144            element.initSettings(m_cms, m_adeConfig, formatter, m_locale, m_req, container.getSettingPresets());
1145            try {
1146                content = getElementContent(element, m_cms.readResource(formatter.getJspStructureId()), container);
1147                //                }
1148            } catch (Exception e) {
1149                LOG.error(e.getLocalizedMessage(), e);
1150            }
1151            if (content != null) {
1152                content = removeScriptTags(content);
1153            }
1154        }
1155        return content;
1156    }
1157
1158    /**
1159     * Returns the rendered element content for all the given containers.
1160     *
1161     * @param element the element to render
1162     * @param containers the containers the element appears in
1163     *
1164     * @return a map from container names to rendered page contents
1165     */
1166    private Map<String, String> getContentsByContainerName(
1167        CmsContainerElementBean element,
1168        Collection<CmsContainer> containers) {
1169
1170        CmsFormatterConfiguration configs = getFormatterConfiguration(element.getResource());
1171        Map<String, String> result = new HashMap<String, String>();
1172        for (CmsContainer container : containers) {
1173            String content = getContentByContainer(element, container, configs);
1174            if (content != null) {
1175                content = removeScriptTags(content);
1176            }
1177            result.put(container.getName(), content);
1178        }
1179        return result;
1180    }
1181
1182    /**
1183     * Returns the content of an element when rendered with the given formatter.<p>
1184     *
1185     * @param element the element bean
1186     * @param formatter the formatter uri
1187     * @param container the container for which the element content should be retrieved
1188     *
1189     * @return generated html code
1190     *
1191     * @throws CmsException if an cms related error occurs
1192     * @throws ServletException if a jsp related error occurs
1193     *
1194     * @throws IOException if a jsp related error occurs
1195     */
1196    private String getElementContent(CmsContainerElementBean element, CmsResource formatter, CmsContainer container)
1197    throws CmsException, ServletException, IOException {
1198
1199        element.initResource(m_cms);
1200        TemplateBean templateBean = CmsADESessionCache.getCache(m_req, m_cms).getTemplateBean(
1201            m_cms.addSiteRoot(m_currentPageUri),
1202            true);
1203        String oldUri = m_cms.getRequestContext().getUri();
1204        try {
1205            m_cms.getRequestContext().setUri(m_currentPageUri);
1206            CmsContainerBean containerBean = null;
1207            if ((m_standardContext.getPage() != null)
1208                && m_standardContext.getPage().getContainers().containsKey(container.getName())) {
1209                containerBean = m_standardContext.getPage().getContainers().get(container.getName());
1210            } else {
1211                containerBean = CmsElementUtil.clientToServerContainer(
1212                    container,
1213                    Collections.<CmsContainerElementBean> emptyList());
1214            }
1215            if (containerBean.getWidth() == null) {
1216                containerBean.setWidth(String.valueOf(container.getWidth()));
1217            }
1218            containerBean.setDetailOnly(container.isDetailOnly());
1219            m_standardContext.setContainer(containerBean);
1220            m_standardContext.setElement(element);
1221            m_standardContext.setEdited(true);
1222            // to enable 'old' direct edit features for content-collector-elements,
1223            // set the direct-edit-provider-attribute in the request
1224            I_CmsDirectEditProvider eb = new CmsAdvancedDirectEditProvider();
1225            eb.init(m_cms, CmsDirectEditMode.TRUE, element.getSitePath());
1226            m_req.setAttribute(I_CmsDirectEditProvider.ATTRIBUTE_DIRECT_EDIT_PROVIDER, eb);
1227            m_req.setAttribute(CmsTemplateContextManager.ATTR_TEMPLATE_BEAN, templateBean);
1228            String encoding = m_res.getCharacterEncoding();
1229            return (new String(
1230                OpenCms.getResourceManager().getLoader(formatter).dump(m_cms, formatter, null, m_locale, m_req, m_res),
1231                encoding)).trim();
1232        } finally {
1233            m_cms.getRequestContext().setUri(oldUri);
1234        }
1235    }
1236
1237    /**
1238     * Gets the lock information.
1239     *
1240     * @param cms the current CMS context
1241     * @param resource the resource for which to get lock information
1242     * @return the lock information
1243     */
1244    private CmsElementLockInfo getLockInfo(CmsObject cms, CmsResource resource) {
1245
1246        try {
1247            CmsLock lock = cms.getLock(resource);
1248            CmsUUID owner = lock.getUserId();
1249            boolean isPublish = lock.isPublish();
1250            return new CmsElementLockInfo(owner, isPublish);
1251        } catch (Exception e) {
1252            LOG.error(e.getLocalizedMessage(), e);
1253            return new CmsElementLockInfo(null, false);
1254        }
1255    }
1256
1257    /**
1258     * Helper method for checking whether there are properties defined for a given content element.<p>
1259     *
1260     * @param cms the CmsObject to use for VFS operations
1261     * @param resource the resource for which it should be checked whether it has properties
1262     *
1263     * @return true if the resource has properties defined
1264     *
1265     * @throws CmsException if something goes wrong
1266     */
1267    private boolean hasSettings(CmsObject cms, CmsResource resource) throws CmsException {
1268
1269        if (!CmsResourceTypeXmlContent.isXmlContent(resource)) {
1270            return false;
1271        }
1272
1273        CmsADEConfigData config = getConfigData();
1274        CmsFormatterConfiguration formatters = config.getFormatters(m_cms, resource);
1275        boolean result = (formatters.getAllFormatters().size() > 1)
1276            || !CmsXmlContentPropertyHelper.getPropertyInfo(m_cms, null, resource).isEmpty();
1277        if (!result && (formatters.getAllFormatters().size() == 1)) {
1278            result = (formatters.getAllFormatters().get(0).getSettings(config).size() > 0);
1279        }
1280        return result;
1281    }
1282
1283    /**
1284     * Parses the given request parameters string into a parameter map.<p>
1285     *
1286     * @param requestParameters the request parameters to parse
1287     *
1288     * @return the parameter map
1289     */
1290    private Map<String, Object> parseRequestParameters(String requestParameters) {
1291
1292        Map<String, Object> parameterMap;
1293        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(requestParameters)) {
1294            parameterMap = new HashMap<String, Object>();
1295            String[] params = requestParameters.split("&");
1296            for (int i = 0; i < params.length; i++) {
1297                int position = params[i].indexOf("=");
1298                if (position >= 0) {
1299                    String key = params[i].substring(0, position);
1300                    String value = params[i].substring(position + 1);
1301                    if (value.contains(",")) {
1302                        parameterMap.put(key, value.split(","));
1303                    } else {
1304                        parameterMap.put(key, value);
1305                    }
1306                }
1307            }
1308        } else {
1309            parameterMap = Collections.<String, Object> emptyMap();
1310        }
1311        return parameterMap;
1312    }
1313
1314    /**
1315     * Removes all script tags from given input.<p>
1316     *
1317     * @param input the input to remove script tags from
1318     *
1319     * @return the cleaned input
1320     */
1321    private String removeScriptTags(String input) {
1322
1323        Pattern removePattern = Pattern.compile("<script[^>]*?>[\\s\\S]*?<\\/script>");
1324        Matcher match = removePattern.matcher(input);
1325        return match.replaceAll("");
1326    }
1327}