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.jsp;
029
030import org.opencms.ade.configuration.CmsADEConfigData;
031import org.opencms.ade.containerpage.CmsDetailOnlyContainerUtil;
032import org.opencms.file.CmsObject;
033import org.opencms.file.CmsResource;
034import org.opencms.file.CmsResourceFilter;
035import org.opencms.file.types.CmsResourceTypeXmlContent;
036import org.opencms.file.types.I_CmsResourceType;
037import org.opencms.flex.CmsFlexController;
038import org.opencms.jsp.util.CmsJspStandardContextBean;
039import org.opencms.loader.CmsLoaderException;
040import org.opencms.main.CmsException;
041import org.opencms.main.CmsLog;
042import org.opencms.main.OpenCms;
043import org.opencms.util.CmsStringUtil;
044import org.opencms.util.CmsUUID;
045import org.opencms.xml.CmsXmlContentDefinition;
046import org.opencms.xml.containerpage.CmsContainerBean;
047import org.opencms.xml.containerpage.CmsContainerElementBean;
048import org.opencms.xml.containerpage.CmsContainerPageBean;
049import org.opencms.xml.containerpage.CmsFormatterConfiguration;
050import org.opencms.xml.containerpage.I_CmsFormatterBean;
051
052import java.io.IOException;
053import java.io.UnsupportedEncodingException;
054import java.net.URLEncoder;
055import java.util.ArrayList;
056import java.util.Collections;
057import java.util.HashMap;
058import java.util.LinkedHashMap;
059import java.util.LinkedHashSet;
060import java.util.List;
061import java.util.Map;
062import java.util.Map.Entry;
063import java.util.Set;
064
065import javax.servlet.ServletRequest;
066import javax.servlet.http.HttpServletRequest;
067import javax.servlet.jsp.JspException;
068import javax.servlet.jsp.tagext.BodyTagSupport;
069
070import org.apache.commons.logging.Log;
071
072import com.google.common.collect.Lists;
073
074/**
075 * This tag includes required CSS or JavaScript resources that are to be places in the HTML head.<p>
076 *
077 * Required resources can be configured in the resource type schema.
078 * Set attribute type to 'css' to include css resources or to 'javascript' to include JavaScript resources.<p>
079 *
080 * @since 8.0
081 */
082public class CmsJspTagHeadIncludes extends BodyTagSupport implements I_CmsJspTagParamParent {
083
084    /** The include type CSS. */
085    public static final String TYPE_CSS = "css";
086
087    /** The include type java-script. */
088    public static final String TYPE_JAVASCRIPT = "javascript";
089
090    /** The log object for this class. */
091    private static final Log LOG = CmsLog.getLog(CmsJspTagHeadIncludes.class);
092
093    /** Serial version UID required for safe serialisation. */
094    private static final long serialVersionUID = 5496349529835666345L;
095
096    /** The value of the closetags attribute. */
097    private String m_closeTags;
098
099    /** The default include resources separated by '|'. */
100    private String m_defaults;
101
102    /** The detail container type. */
103    private String m_detailType;
104
105    /** The detail container width. */
106    private String m_detailWidth;
107
108    /** Map to save parameters to the include in. */
109    private Map<String, String[]> m_parameterMap;
110
111    /** The include type. */
112    private String m_type;
113
114    /**
115     * Adds parameters to a parameter Map that can be used for a http request.<p>
116     *
117     * @param parameters the Map to add the parameters to
118     * @param name the name to add
119     * @param value the value to add
120     * @param overwrite if <code>true</code>, a parameter in the map will be overwritten by
121     *      a parameter with the same name, otherwise the request will have multiple parameters
122     *      with the same name (which is possible in http requests)
123     */
124    public static void addParameter(Map<String, String[]> parameters, String name, String value, boolean overwrite) {
125
126        // No null values allowed in parameters
127        if ((parameters == null) || (name == null) || (value == null)) {
128            return;
129        }
130
131        // Check if the parameter name (key) exists
132        if (parameters.containsKey(name) && (!overwrite)) {
133            // Yes: Check name values if value exists, if so do nothing, else add new value
134            String[] values = parameters.get(name);
135            String[] newValues = new String[values.length + 1];
136            System.arraycopy(values, 0, newValues, 0, values.length);
137            newValues[values.length] = value;
138            parameters.put(name, newValues);
139        } else {
140            // No: Add new parameter name / value pair
141            String[] values = new String[] {value};
142            parameters.put(name, values);
143        }
144    }
145
146    /**
147     * Gets the head includes for the given formatter bean.<p>
148     *
149     * @param formatter the formatter bean
150     * @param type the head include type
151     *
152     * @return the list of head includes
153     */
154    protected static List<String> getHeadIncludes(I_CmsFormatterBean formatter, String type) {
155
156        if (TYPE_CSS.equals(type)) {
157            return Lists.newArrayList(formatter.getCssHeadIncludes());
158        } else if (TYPE_JAVASCRIPT.equals(type)) {
159            return formatter.getJavascriptHeadIncludes();
160        }
161        return null;
162    }
163
164    /**
165     * Gets the inline CSS/Javascrip for the given formatter bean.<p>
166     *
167     * @param formatter the formatter bean
168     * @param type the type (CSS or Javascript)
169     *
170     * @return the inline data for the given formatter bean
171     */
172    protected static String getInlineData(I_CmsFormatterBean formatter, String type) {
173
174        if (TYPE_CSS.equals(type)) {
175            return formatter.getInlineCss();
176        } else if (TYPE_JAVASCRIPT.equals(type)) {
177            return formatter.getInlineJavascript();
178        }
179        return null;
180    }
181
182    /**
183     * @see org.opencms.jsp.I_CmsJspTagParamParent#addParameter(java.lang.String, java.lang.String)
184     */
185    public void addParameter(String name, String value) {
186
187        // No null values allowed in parameters
188        if ((name == null) || (value == null)) {
189            return;
190        }
191
192        // Check if internal map exists, create new one if not
193        if (m_parameterMap == null) {
194            m_parameterMap = new HashMap<String, String[]>();
195        }
196
197        addParameter(m_parameterMap, name, value, false);
198
199    }
200
201    /**
202     * @return <code>EVAL_PAGE</code>
203     *
204     * @see javax.servlet.jsp.tagext.Tag#doEndTag()
205     *
206     * @throws JspException by interface default
207     */
208    @Override
209    public int doEndTag() throws JspException {
210
211        ServletRequest req = pageContext.getRequest();
212        CmsFlexController controller = CmsFlexController.getController(req);
213        CmsObject cms = controller.getCmsObject();
214        try {
215            if (TYPE_CSS.equals(m_type)) {
216                tagCssAction(cms, (HttpServletRequest)req);
217            }
218            if (TYPE_JAVASCRIPT.equals(m_type)) {
219                tagJSAction(cms, (HttpServletRequest)req);
220            }
221        } catch (Exception e) {
222            throw new JspException(e);
223        } finally {
224            m_parameterMap = null;
225        }
226        return EVAL_PAGE;
227
228    }
229
230    /**
231     * Returns <code>{@link #EVAL_BODY_BUFFERED}</code>.<p>
232     *
233     * @return <code>{@link #EVAL_BODY_BUFFERED}</code>
234     *
235     * @see javax.servlet.jsp.tagext.Tag#doStartTag()
236     */
237    @Override
238    public int doStartTag() {
239
240        return EVAL_BODY_BUFFERED;
241    }
242
243    /**
244     * Returns the default include resources separated by '|'.<p>
245     *
246     * @return the default include resources
247     */
248    public String getDefaults() {
249
250        return m_defaults;
251    }
252
253    /**
254     * Returns the detail container type.<p>
255     *
256     * @return the detail container type
257     */
258    public String getDetailtype() {
259
260        return m_detailType;
261    }
262
263    /**
264     * Returns the detail container width.<p>
265     *
266     * @return the detail container width
267     */
268    public String getDetailwidth() {
269
270        return m_detailWidth;
271    }
272
273    /**
274     * Returns the type.<p>
275     *
276     * @return the type
277     */
278    public String getType() {
279
280        return m_type;
281    }
282
283    /**
284     * Sets the value of the closetags attribute.<p>
285     *
286     * @param closeTags the value of the closetags attribute
287     */
288    public void setClosetags(String closeTags) {
289
290        m_closeTags = closeTags;
291    }
292
293    /**
294     * Sets the default include resources separated by '|'.<p>
295     *
296     * @param defaults the default include resources to set
297     */
298    public void setDefaults(String defaults) {
299
300        m_defaults = defaults;
301    }
302
303    /**
304     * Sets the detail container type.<p>
305     *
306     * @param detailType the detail container type to set
307     */
308    public void setDetailtype(String detailType) {
309
310        m_detailType = detailType;
311    }
312
313    /**
314     * Sets the detail container width.<p>
315     *
316     * @param detailWidth the detail container width to set
317     */
318    public void setDetailwidth(String detailWidth) {
319
320        m_detailWidth = detailWidth;
321    }
322
323    /**
324     * Sets the type.<p>
325     *
326     * @param type the type to set
327     */
328    public void setType(String type) {
329
330        m_type = type;
331    }
332
333    /**
334     * Returns true if the headincludes tag should be closed.<p>
335     *
336     * @return true if the headincludes tag should be closed
337     */
338    public boolean shouldCloseTags() {
339
340        if (m_closeTags == null) {
341            return true;
342        }
343        return Boolean.parseBoolean(m_closeTags);
344    }
345
346    /**
347     * Action to include the CSS resources.<p>
348     *
349     * @param cms the current cms context
350     * @param req the current request
351     *
352     * @throws CmsException if something goes wrong reading the resources
353     * @throws IOException if something goes wrong writing to the response out
354     */
355    public void tagCssAction(CmsObject cms, HttpServletRequest req) throws CmsException, IOException {
356
357        String includeType = TYPE_CSS;
358
359        CmsJspStandardContextBean standardContext = getStandardContext(cms, req);
360        CmsContainerPageBean containerPage = standardContext.getPage();
361
362        Set<String> cssIncludes = new LinkedHashSet<String>();
363        Map<String, String> inlineCss = new LinkedHashMap<String, String>();
364        // add defaults
365        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_defaults)) {
366            String[] defaults = m_defaults.split("\\|");
367            for (int i = 0; i < defaults.length; i++) {
368                cssIncludes.add(defaults[i].trim());
369            }
370        }
371
372        collectHeadIncludesForContainerElement(
373            cms,
374            req,
375            standardContext,
376            containerPage,
377            includeType,
378            cssIncludes,
379            inlineCss);
380        if (standardContext.getDetailContentId() != null) {
381            try {
382                CmsResource detailContent = cms.readResource(
383                    standardContext.getDetailContentId(),
384                    CmsResourceFilter.ignoreExpirationOffline(cms));
385                CmsFormatterConfiguration config = OpenCms.getADEManager().lookupConfiguration(
386                    cms,
387                    cms.getRequestContext().getRootUri()).getFormatters(cms, detailContent);
388                boolean requiresAllIncludes = true;
389                if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(getDetailtype())
390                    && CmsStringUtil.isNotEmptyOrWhitespaceOnly(getDetailwidth())) {
391                    try {
392                        int width = Integer.parseInt(getDetailwidth());
393                        I_CmsFormatterBean formatter = config.getDetailFormatter(getDetailtype(), width);
394                        cssIncludes.addAll(formatter.getCssHeadIncludes());
395                        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(formatter.getInlineCss())) {
396                            inlineCss.put(formatter.getId(), formatter.getInlineCss());
397                        }
398                        requiresAllIncludes = false;
399                    } catch (NumberFormatException ne) {
400                        // nothing to do, we will include CSS for all detail containers
401                    }
402                }
403                if (requiresAllIncludes) {
404                    for (I_CmsFormatterBean formatter : config.getDetailFormatters()) {
405                        cssIncludes.addAll(getHeadIncludes(formatter, includeType));
406                        String inlineIncludeData = getInlineData(formatter, includeType);
407                        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(inlineIncludeData)) {
408                            inlineCss.put(formatter.getId(), inlineIncludeData);
409                        }
410                    }
411                }
412            } catch (CmsException e) {
413                LOG.error(
414                    Messages.get().getBundle().key(
415                        Messages.ERR_READING_REQUIRED_RESOURCE_1,
416                        standardContext.getDetailContentId()),
417                    e);
418            }
419        }
420        for (String cssUri : cssIncludes) {
421            pageContext.getOut().print(
422                "\n<link rel=\"stylesheet\" href=\""
423                    + CmsJspTagLink.linkTagAction(cssUri.trim(), req)
424                    + generateReqParams()
425                    + "\" type=\"text/css\" ");
426            if (shouldCloseTags()) {
427                pageContext.getOut().print("/>");
428            } else {
429                pageContext.getOut().print(">");
430            }
431        }
432        if (cms.getRequestContext().getCurrentProject().isOnlineProject()) {
433            if (!inlineCss.isEmpty()) {
434                StringBuffer inline = new StringBuffer("\n<style type=\"text/css\">\n");
435                for (Entry<String, String> cssEntry : inlineCss.entrySet()) {
436                    inline.append(cssEntry.getValue()).append("\n\n");
437                }
438                inline.append("\n</style>\n");
439                pageContext.getOut().print(inline.toString());
440            }
441        } else {
442            StringBuffer inline = new StringBuffer();
443            for (Entry<String, String> cssEntry : inlineCss.entrySet()) {
444                inline.append("\n<style type=\"text/css\" rel=\"" + cssEntry.getKey() + "\">\n");
445                inline.append(cssEntry.getValue()).append("\n\n");
446                inline.append("\n</style>\n");
447            }
448            pageContext.getOut().print(inline.toString());
449        }
450    }
451
452    /**
453     * Action to include the java-script resources.<p>
454     *
455     * @param cms the current cms context
456     * @param req the current request
457     *
458     * @throws CmsException if something goes wrong reading the resources
459     * @throws IOException if something goes wrong writing to the response out
460     */
461    public void tagJSAction(CmsObject cms, HttpServletRequest req) throws CmsException, IOException {
462
463        CmsJspStandardContextBean standardContext = getStandardContext(cms, req);
464        CmsContainerPageBean containerPage = standardContext.getPage();
465        String includeType = TYPE_JAVASCRIPT;
466        Set<String> jsIncludes = new LinkedHashSet<String>();
467        Map<String, String> inlineJS = new LinkedHashMap<String, String>();
468        // add defaults
469        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_defaults)) {
470            String[] defaults = m_defaults.split("\\|");
471            for (int i = 0; i < defaults.length; i++) {
472                jsIncludes.add(defaults[i].trim());
473            }
474        }
475        collectHeadIncludesForContainerElement(
476            cms,
477            req,
478            standardContext,
479            containerPage,
480            includeType,
481            jsIncludes,
482            inlineJS);
483        if (standardContext.getDetailContentId() != null) {
484            try {
485                CmsResource detailContent = cms.readResource(
486                    standardContext.getDetailContentId(),
487                    CmsResourceFilter.ignoreExpirationOffline(cms));
488                CmsFormatterConfiguration config = OpenCms.getADEManager().lookupConfiguration(
489                    cms,
490                    cms.getRequestContext().getRootUri()).getFormatters(cms, detailContent);
491                boolean requiresAllIncludes = true;
492                if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(getDetailtype())
493                    && CmsStringUtil.isNotEmptyOrWhitespaceOnly(getDetailwidth())) {
494                    try {
495                        int width = Integer.parseInt(getDetailwidth());
496                        I_CmsFormatterBean formatter = config.getDetailFormatter(getDetailtype(), width);
497                        jsIncludes.addAll(formatter.getJavascriptHeadIncludes());
498                        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(formatter.getInlineJavascript())) {
499                            inlineJS.put(formatter.getId(), formatter.getInlineJavascript());
500                        }
501                        requiresAllIncludes = false;
502                    } catch (NumberFormatException ne) {
503                        // nothing to do, we will include JavaScript for all detail containers
504                    }
505                }
506                if (requiresAllIncludes) {
507                    for (I_CmsFormatterBean formatter : config.getDetailFormatters()) {
508                        jsIncludes.addAll(getHeadIncludes(formatter, includeType));
509                        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(formatter.getInlineJavascript())) {
510                            inlineJS.put(formatter.getId(), formatter.getInlineJavascript());
511                        }
512                    }
513                }
514            } catch (CmsException e) {
515                LOG.error(
516                    Messages.get().getBundle().key(
517                        Messages.ERR_READING_REQUIRED_RESOURCE_1,
518                        standardContext.getDetailContentId()),
519                    e);
520            }
521        }
522        for (String jsUri : jsIncludes) {
523            pageContext.getOut().print(
524                "\n<script type=\"text/javascript\" src=\""
525                    + CmsJspTagLink.linkTagAction(jsUri.trim(), req)
526                    + generateReqParams()
527                    + "\"></script>");
528        }
529        if (!inlineJS.isEmpty()) {
530            StringBuffer inline = new StringBuffer();
531            for (Entry<String, String> jsEntry : inlineJS.entrySet()) {
532                inline.append("\n<script type=\"text/javascript\">\n");
533                inline.append(jsEntry.getValue()).append("\n\n");
534                inline.append("\n</script>\n");
535            }
536            pageContext.getOut().print(inline.toString());
537        }
538    }
539
540    /**
541     * Collects the head includes for a given container element.<p>
542     *
543     * @param cms the current CMS context
544     * @param req the current request
545     * @param standardContext the current standard context
546     * @param containerPage the current container page
547     * @param includeType the type of head includes (CSS or Javascript)
548     * @param headincludes the set to which normal head includes should be added
549     * @param inline the map to which inline head includes should be added
550     */
551    protected void collectHeadIncludesForContainerElement(
552        CmsObject cms,
553        ServletRequest req,
554        CmsJspStandardContextBean standardContext,
555        CmsContainerPageBean containerPage,
556        String includeType,
557        Set<String> headincludes,
558        Map<String, String> inline) {
559
560        CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration(
561            cms,
562            cms.getRequestContext().getRootUri());
563        if ((containerPage != null) && (containerPage.getElements() != null)) {
564            Map<CmsUUID, I_CmsFormatterBean> formatters = OpenCms.getADEManager().getCachedFormatters(
565                standardContext.getIsOnlineProject()).getFormatters();
566            List<CmsContainerBean> containers = new ArrayList<CmsContainerBean>(containerPage.getContainers().values());
567            // add detail only containers if available
568            if (standardContext.isDetailRequest()) {
569                CmsContainerPageBean detailOnly = CmsDetailOnlyContainerUtil.getDetailOnlyPage(
570                    cms,
571                    req,
572                    cms.getRequestContext().getRootUri());
573                if (detailOnly != null) {
574                    containers.addAll(detailOnly.getContainers().values());
575                }
576            }
577            for (CmsContainerBean container : containers) {
578                for (CmsContainerElementBean element : container.getElements()) {
579                    try {
580                        element.initResource(cms);
581                        if (!standardContext.getIsOnlineProject()
582                            || element.getResource().isReleasedAndNotExpired(
583                                cms.getRequestContext().getRequestTime())) {
584                            if (element.isGroupContainer(cms) || element.isInheritedContainer(cms)) {
585                                List<CmsContainerElementBean> subElements;
586                                if (element.isGroupContainer(cms)) {
587                                    subElements = CmsJspTagContainer.getGroupContainerElements(
588                                        cms,
589                                        element,
590                                        req,
591                                        container.getType());
592                                } else {
593                                    subElements = CmsJspTagContainer.getInheritedContainerElements(cms, element);
594                                }
595                                for (CmsContainerElementBean subElement : subElements) {
596                                    subElement.initResource(cms);
597                                    if (!standardContext.getIsOnlineProject()
598                                        || subElement.getResource().isReleasedAndNotExpired(
599                                            cms.getRequestContext().getRequestTime())) {
600                                        I_CmsFormatterBean formatter = getFormatterBeanForElement(
601                                            cms,
602                                            config,
603                                            subElement,
604                                            container,
605                                            formatters);
606                                        if (formatter != null) {
607                                            headincludes.addAll(getHeadIncludes(formatter, includeType));
608                                            String inlineIncludeData = getInlineData(formatter, includeType);
609                                            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(inlineIncludeData)) {
610                                                inline.put(formatter.getId(), inlineIncludeData);
611                                            }
612                                        } else {
613
614                                            headincludes.addAll(
615                                                getSchemaHeadIncludes(cms, subElement.getResource(), includeType));
616                                        }
617                                    }
618                                }
619                            } else {
620                                I_CmsFormatterBean formatter = getFormatterBeanForElement(
621                                    cms,
622                                    config,
623                                    element,
624                                    container,
625                                    formatters);
626                                if (formatter != null) {
627                                    headincludes.addAll(getHeadIncludes(formatter, includeType));
628                                    String inlineIncludeData = getInlineData(formatter, includeType);
629                                    if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(inlineIncludeData)) {
630                                        inline.put(formatter.getId(), inlineIncludeData);
631                                    }
632                                } else {
633
634                                    headincludes.addAll(getSchemaHeadIncludes(cms, element.getResource(), includeType));
635                                }
636                            }
637                        }
638                    } catch (CmsException e) {
639                        LOG.error(
640                            Messages.get().getBundle().key(
641                                Messages.ERR_READING_REQUIRED_RESOURCE_1,
642                                element.getSitePath()),
643                            e);
644                    }
645                }
646            }
647        }
648    }
649
650    /**
651     * Generates the request parameter string.<p>
652     *
653     * @return the request parameter string
654     *
655     * @throws UnsupportedEncodingException if something goes wrong encoding the request parameters
656     */
657    private String generateReqParams() throws UnsupportedEncodingException {
658
659        String params = "";
660        if ((m_parameterMap != null) && !m_parameterMap.isEmpty()) {
661            for (Entry<String, String[]> paramEntry : m_parameterMap.entrySet()) {
662                if (paramEntry.getValue() != null) {
663                    for (int i = 0; i < paramEntry.getValue().length; i++) {
664                        params += "&"
665                            + paramEntry.getKey()
666                            + "="
667                            + URLEncoder.encode(paramEntry.getValue()[i], "UTF-8");
668                    }
669                }
670            }
671            params = "?" + params.substring(1);
672        }
673        return params;
674    }
675
676    /**
677     * Returns the schema configured CSS head include resources.<p>
678     *
679     * @param cms the current cms context
680     * @param resource the resource
681     *
682     * @return the configured CSS head include resources
683     */
684    private Set<String> getCSSHeadIncludes(CmsObject cms, CmsResource resource) {
685
686        if (CmsResourceTypeXmlContent.isXmlContent(resource)) {
687            try {
688                CmsXmlContentDefinition contentDefinition = CmsXmlContentDefinition.getContentDefinitionForResource(
689                    cms,
690                    resource);
691                return contentDefinition.getContentHandler().getCSSHeadIncludes(cms, resource);
692            } catch (CmsException e) {
693                LOG.warn(e.getLocalizedMessage(), e);
694                // NOOP, use the empty set
695            }
696        }
697        return Collections.emptySet();
698    }
699
700    /**
701     * Returns the formatter configuration for the given element, will return <code>null</code> for schema formatters.<p>
702     *
703     * @param cms the current CMS context
704     * @param config the current sitemap configuration
705     * @param element the element bean
706     * @param container the container bean
707     * @param formatters the formatter map
708     *
709     * @return the formatter configuration bean
710     */
711    private I_CmsFormatterBean getFormatterBeanForElement(
712        CmsObject cms,
713        CmsADEConfigData config,
714        CmsContainerElementBean element,
715        CmsContainerBean container,
716        Map<CmsUUID, I_CmsFormatterBean> formatters) {
717
718        int containerWidth = -1;
719        if (container.getWidth() == null) {
720            // the container width has not been set yet
721            containerWidth = CmsFormatterConfiguration.MATCH_ALL_CONTAINER_WIDTH;
722        } else {
723            try {
724
725                containerWidth = Integer.parseInt(container.getWidth());
726            } catch (NumberFormatException e) {
727                // do nothing, set width to -1
728            }
729        }
730        I_CmsFormatterBean result = CmsJspTagContainer.getFormatterConfigurationForElement(
731            cms,
732            element,
733            config,
734            container.getName(),
735            container.getType(),
736            containerWidth);
737        return result;
738    }
739
740    /**
741     * Returns the schema configured JavaScript head include resources.<p>
742     *
743     * @param cms the current cms context
744     * @param resource the resource
745     *
746     * @return the configured JavaScript head include resources
747     *
748     * @throws CmsLoaderException if something goes wrong reading the resource type
749     */
750    private Set<String> getJSHeadIncludes(CmsObject cms, CmsResource resource) throws CmsLoaderException {
751
752        I_CmsResourceType resType = OpenCms.getResourceManager().getResourceType(resource.getTypeId());
753        if (resType instanceof CmsResourceTypeXmlContent) {
754            try {
755                CmsXmlContentDefinition contentDefinition = CmsXmlContentDefinition.getContentDefinitionForResource(
756                    cms,
757                    resource);
758                return contentDefinition.getContentHandler().getJSHeadIncludes(cms, resource);
759            } catch (CmsException e) {
760                LOG.warn(e.getLocalizedMessage(), e);
761                // NOOP, use the empty set
762            }
763        }
764        return Collections.emptySet();
765    }
766
767    /**
768     * Gets the head includes of a resource from the content definition.<p>
769     *
770     * @param cms the current CMS context
771     * @param res the resource for which the head includes should be fetched
772     * @param type the head include type (CSS or Javascript)
773     *
774     * @return the set of schema head includes
775     *
776     * @throws CmsLoaderException if something goes wrong
777     */
778    private Set<String> getSchemaHeadIncludes(CmsObject cms, CmsResource res, String type) throws CmsLoaderException {
779
780        if (type.equals(TYPE_CSS)) {
781            return getCSSHeadIncludes(cms, res);
782        } else if (type.equals(TYPE_JAVASCRIPT)) {
783            return getJSHeadIncludes(cms, res);
784        }
785        return null;
786    }
787
788    /**
789     * Returns the standard context bean.<p>
790     *
791     * @param cms the current cms context
792     * @param req the current request
793     *
794     * @return the standard context bean
795     *
796     * @throws CmsException if something goes wrong
797     */
798    private CmsJspStandardContextBean getStandardContext(CmsObject cms, HttpServletRequest req) throws CmsException {
799
800        CmsJspStandardContextBean standardContext = CmsJspStandardContextBean.getInstance(req);
801        standardContext.initPage();
802        return standardContext;
803    }
804
805}