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.configuration.formatters.CmsFormatterConfigurationCacheState;
032import org.opencms.file.CmsObject;
033import org.opencms.file.CmsResource;
034import org.opencms.file.CmsResourceFilter;
035import org.opencms.file.collectors.I_CmsCollectorPostCreateHandler;
036import org.opencms.flex.CmsFlexController;
037import org.opencms.jsp.util.CmsJspStandardContextBean;
038import org.opencms.main.CmsException;
039import org.opencms.main.CmsLog;
040import org.opencms.main.OpenCms;
041import org.opencms.util.CmsStringUtil;
042import org.opencms.util.CmsUUID;
043import org.opencms.xml.containerpage.CmsContainerElementBean;
044import org.opencms.xml.containerpage.I_CmsFormatterBean;
045
046import java.util.HashMap;
047import java.util.LinkedHashMap;
048import java.util.Map;
049import java.util.Map.Entry;
050
051import javax.servlet.ServletRequest;
052import javax.servlet.ServletResponse;
053import javax.servlet.jsp.tagext.BodyTagSupport;
054
055import org.apache.commons.logging.Log;
056
057/**
058 * The 'simpledisplay' tag can be used to display a single resource using a formatter. It also allows to activate direct editing.<p>
059 * It is less flexible but simpler to use than the 'display' tag in that it only allows you to specify a single, fixed formatter configuration as an attribute,
060 * rather than a set of type-dependent formatters with the displayformatter tag.
061 *
062 */
063public class CmsJspTagSimpleDisplay extends BodyTagSupport implements I_CmsJspTagParamParent {
064
065    /** The log object for this class. */
066    private static final Log LOG = CmsLog.getLog(CmsJspTagSimpleDisplay.class);
067
068    /** The serial version id. */
069    private static final long serialVersionUID = 2285680951218629093L;
070
071    /** True if the display formatter include should go through the flex cache. */
072    private Boolean m_cacheable;
073
074    /** Flag, indicating if the create option should be displayed. */
075    private boolean m_canCreate;
076
077    /** Flag, indicating if the delete option should be displayed. */
078    private boolean m_canDelete;
079
080    /** The tag attribute's value, specifying the path to the (sub)sitemap where new content should be created. */
081    private String m_creationSiteMap;
082
083    /** The editable flag. */
084    private boolean m_editable;
085
086    /** The formatter key. */
087    private String m_formatterKey;
088
089    /** Stores the formatter path. */
090    private String m_formatterPath;
091
092    /** The settings parameter map. */
093    private Map<String, String> m_parameterMap;
094
095    /** The pass settings flag. */
096    private boolean m_passSettings;
097
098    /** The fully qualified class name of the post create handler to use. */
099    private String m_postCreateHandler;
100
101    /** The element settings to be used. */
102    private Map<String, String> m_settings;
103
104    /** The upload folder. */
105    private String m_uploadFolder;
106
107    /** The site path to the resource to display. */
108    private String m_value;
109
110    /**
111     * Constructor.<p>
112     */
113    public CmsJspTagSimpleDisplay() {
114
115        m_parameterMap = new LinkedHashMap<String, String>();
116    }
117
118    /**
119     * @see org.opencms.jsp.I_CmsJspTagParamParent#addParameter(java.lang.String, java.lang.String)
120     */
121    public void addParameter(String name, String value) {
122
123        // No null values allowed in parameters
124        if ((name == null) || (value == null)) {
125            return;
126        }
127
128        m_parameterMap.put(name, value);
129    }
130
131    /**
132     * @see javax.servlet.jsp.tagext.BodyTagSupport#doEndTag()
133     */
134    @Override
135    public int doEndTag() {
136
137        ServletRequest request = pageContext.getRequest();
138        ServletResponse response = pageContext.getResponse();
139        if (CmsFlexController.isCmsRequest(request)) {
140            // this will always be true if the page is called through OpenCms
141            CmsObject cms = CmsFlexController.getCmsObject(request);
142            try {
143                boolean isOnline = cms.getRequestContext().getCurrentProject().isOnlineProject();
144                CmsResource res = null;
145                if (CmsUUID.isValidUUID(m_value)) {
146                    CmsUUID structureId = new CmsUUID(m_value);
147                    res = isOnline
148                    ? cms.readResource(structureId)
149                    : cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
150                } else {
151                    res = isOnline
152                    ? cms.readResource(m_value)
153                    : cms.readResource(m_value, CmsResourceFilter.IGNORE_EXPIRATION);
154                }
155                CmsADEConfigData config = OpenCms.getADEManager().lookupConfigurationWithCache(
156                    cms,
157                    cms.getRequestContext().getRootUri());
158                I_CmsFormatterBean formatter = getFormatterBean(cms, config);
159
160                Map<String, String> settings = new HashMap<String, String>();
161                for (Entry<String, String> entry : m_parameterMap.entrySet()) {
162                    String settingKeySuffix = CmsJspTagDisplay.getSettingKeyForMatchingFormatterPrefix(
163                        config,
164                        formatter,
165                        entry.getKey());
166                    if (settingKeySuffix != null) {
167                        settings.put(settingKeySuffix, entry.getValue());
168                    } else if (!settings.containsKey(entry.getKey())) {
169                        settings.put(entry.getKey(), entry.getValue());
170                    }
171                }
172
173                CmsJspTagDisplay.displayAction(
174                    res,
175                    formatter,
176                    settings,
177                    isCacheable(),
178                    m_editable,
179                    m_canCreate,
180                    m_canDelete,
181                    m_creationSiteMap,
182                    m_postCreateHandler,
183                    m_uploadFolder,
184                    pageContext,
185                    request,
186                    response);
187            } catch (CmsException e) {
188                LOG.error(e.getLocalizedMessage(), e);
189            }
190        }
191        release();
192        return EVAL_PAGE;
193    }
194
195    /**
196     * @see javax.servlet.jsp.tagext.BodyTagSupport#doStartTag()
197     */
198    @Override
199    public int doStartTag() {
200
201        if (Boolean.valueOf(m_passSettings).booleanValue()) {
202            CmsContainerElementBean element = CmsJspStandardContextBean.getInstance(
203                pageContext.getRequest()).getElement();
204            if (element != null) {
205                m_parameterMap.putAll(element.getSettings());
206            }
207        }
208        if (m_settings != null) {
209            m_parameterMap.putAll(m_settings);
210        }
211
212        return EVAL_BODY_BUFFERED;
213    }
214
215    /**
216     * Returns the editable.<p>
217     *
218     * @return the editable
219     */
220    public boolean getEditable() {
221
222        return m_editable;
223    }
224
225    /**
226     * Returns the passSettings.<p>
227     *
228     * @return the passSettings
229     */
230    public boolean getPassSettings() {
231
232        return m_passSettings;
233    }
234
235    /**
236     * Returns the element settings to be used.<p>
237     *
238     * @return the element settings to be used
239     */
240    public Map<String, String> getSettings() {
241
242        return m_settings;
243    }
244
245    /**
246     * Returns the value.<p>
247     *
248     * @return the value
249     */
250    public String getValue() {
251
252        return m_value;
253    }
254
255    /**
256     * @see javax.servlet.jsp.tagext.BodyTagSupport#release()
257     */
258    @Override
259    public void release() {
260
261        super.release();
262        m_parameterMap.clear();
263        m_settings = null;
264        m_passSettings = false;
265        m_editable = false;
266        m_value = null;
267    }
268
269    /**
270     * Sets the 'cacheable' attribute.
271     *
272     * @param cacheable controls whether the JSP include should go through the Flex cache or not
273     */
274    public void setCacheable(boolean cacheable) {
275
276        m_cacheable = Boolean.valueOf(cacheable);
277    }
278
279    /** Setter for the "create" attribute of the tag.
280     * @param canCreate value of the tag's attribute "create".
281     */
282    public void setCreate(boolean canCreate) {
283
284        m_canCreate = canCreate;
285    }
286
287    /** Setter for the "create" attribute of the tag.
288     * @param canCreate value of the tag's attribute "create".
289     */
290    public void setCreate(String canCreate) {
291
292        m_canCreate = Boolean.valueOf(canCreate).booleanValue();
293    }
294
295    /** Setter for the "creationSiteMap" attribute of the tag.
296     * @param sitePath value of the "creationSiteMap" attribute of the tag.
297     */
298    public void setCreationSiteMap(String sitePath) {
299
300        m_creationSiteMap = sitePath;
301    }
302
303    /**Setter for the "delete" attribute of the tag.
304     * @param canDelete value of the "delete" attribute of the tag.
305     */
306    public void setDelete(boolean canDelete) {
307
308        m_canDelete = canDelete;
309    }
310
311    /**Setter for the "delete" attribute of the tag.
312     * @param canDelete value of the "delete" attribute of the tag.
313     */
314    public void setDelete(String canDelete) {
315
316        m_canDelete = Boolean.valueOf(canDelete).booleanValue();
317    }
318
319    /**
320     * Sets the editable.<p>
321     *
322     * @param editable the editable to set
323     */
324    public void setEditable(boolean editable) {
325
326        m_editable = editable;
327    }
328
329    /**
330     * Sets the editable.<p>
331     *
332     * @param editable the editable to set
333     */
334    public void setEditable(String editable) {
335
336        m_editable = Boolean.valueOf(editable).booleanValue();
337    }
338
339    /**
340     * Sets the formatter path.<p>
341     *
342     * @param formatter the formatter path
343     */
344    public void setFormatter(String formatter) {
345
346        m_formatterPath = formatter;
347    }
348
349    /**
350     * Sets the formatter key.
351     *
352     * @param formatterKey the formatter key
353     */
354    public void setFormatterKey(String formatterKey) {
355
356        m_formatterKey = formatterKey;
357    }
358
359    /**
360     * Sets the passSettings.<p>
361     *
362     * @param passSettings the passSettings to set
363     */
364    public void setPassSettings(Boolean passSettings) {
365
366        m_passSettings = passSettings.booleanValue();
367    }
368
369    /** Setter for the "postCreateHandler" attribute of the tag.
370     * @param postCreateHandler fully qualified class name of the {@link I_CmsCollectorPostCreateHandler} to use.
371     */
372    public void setPostCreateHandler(final String postCreateHandler) {
373
374        m_postCreateHandler = postCreateHandler;
375    }
376
377    /**
378     * Sets the element settings to be used.<p>
379     *
380     * @param settings the element settings to be used
381     */
382    public void setSettings(Map<String, String> settings) {
383
384        m_settings = settings;
385    }
386
387    /**
388     * Sets the upload folder.
389     *
390     * @param uploadFolder the upload folder
391     */
392    public void setUploadFolder(String uploadFolder) {
393
394        m_uploadFolder = uploadFolder;
395    }
396
397    /**
398     * Sets the value.<p>
399     *
400     * @param value the value to set
401     */
402    public void setValue(String value) {
403
404        m_value = value;
405    }
406
407    /**
408     * Gets the formatter bean to use, using either the formatter key or formatter path given as attributes.<p>
409     *
410     * If both the formatter and formatterKey attributes are used, a formatter found for the key is prioritized over
411     * the one found for the formatter, if it exists.
412     *
413     * @param cms the CMS context
414     * @param config the active sitemap configuration
415     * @return the formatter to use
416     *
417     * @throws CmsException if something goes wrong
418     */
419    private I_CmsFormatterBean getFormatterBean(CmsObject cms, CmsADEConfigData config) throws CmsException {
420
421        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(m_formatterKey)) {
422
423            I_CmsFormatterBean formatterForKey = config.findFormatter(m_formatterKey);
424            if (formatterForKey != null) {
425                return formatterForKey;
426            }
427        }
428        CmsResource formatterResource = cms.readResource(m_formatterPath);
429        CmsFormatterConfigurationCacheState formatterCache = OpenCms.getADEManager().getCachedFormatters(
430            cms.getRequestContext().getCurrentProject().isOnlineProject());
431        I_CmsFormatterBean formatter = formatterCache.getFormatters().get(formatterResource.getStructureId());
432        return formatter;
433    }
434
435    /**
436     * Checks if this tag instance should use the flex cache for including the formatter.
437     *
438     * @return true if this tag instance should use the flex cache for including the formatter
439     */
440    private boolean isCacheable() {
441
442        return (m_cacheable == null) || m_cacheable.booleanValue();
443    }
444
445}