All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencms.jsp.CmsJspTagInclude Maven / Gradle / Ivy

/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * For further information about Alkacon Software GmbH & Co. KG, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.jsp;

import org.opencms.file.CmsFile;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsPropertyDefinition;
import org.opencms.flex.CmsFlexController;
import org.opencms.flex.CmsFlexResponse;
import org.opencms.loader.CmsJspLoader;
import org.opencms.loader.CmsLoaderException;
import org.opencms.loader.I_CmsResourceLoader;
import org.opencms.loader.I_CmsResourceStringDumpLoader;
import org.opencms.main.CmsException;
import org.opencms.main.OpenCms;
import org.opencms.staticexport.CmsLinkManager;
import org.opencms.util.CmsCollectionsGenericWrapper;
import org.opencms.util.CmsRequestUtil;
import org.opencms.util.CmsStringUtil;
import org.opencms.workplace.editors.directedit.CmsDirectEditParams;

import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyTagSupport;

import com.google.common.collect.Maps;

/**
 * Implementation of the <cms:include/> tag,
 * used to include another OpenCms managed resource in a JSP.

* * @since 6.0.0 */ public class CmsJspTagInclude extends BodyTagSupport implements I_CmsJspTagParamParent { /** Serial version UID required for safe serialization. */ private static final long serialVersionUID = 705978510743164951L; /** The value of the "attribute" attribute. */ private String m_attribute; /** The value of the "cacheable" attribute. */ private boolean m_cacheable; /** The value of the "editable" attribute. */ private boolean m_editable; /** The value of the "element" attribute. */ private String m_element; /** Map to save parameters to the include in. */ private Map m_parameterMap; /** The value of the "property" attribute. */ private String m_property; /** The value of the "suffix" attribute. */ private String m_suffix; /** The value of the "page" attribute. */ private String m_target; /** * Empty constructor, required for attribute value initialization.

*/ public CmsJspTagInclude() { super(); m_cacheable = true; } /** * Adds parameters to a parameter Map that can be used for a http request.

* * @param parameters the Map to add the parameters to * @param name the name to add * @param value the value to add * @param overwrite if true, a parameter in the map will be overwritten by * a parameter with the same name, otherwise the request will have multiple parameters * with the same name (which is possible in http requests) */ public static void addParameter(Map parameters, String name, String value, boolean overwrite) { // No null values allowed in parameters if ((parameters == null) || (name == null) || (value == null)) { return; } // Check if the parameter name (key) exists if (parameters.containsKey(name) && (!overwrite)) { // Yes: Check name values if value exists, if so do nothing, else add new value String[] values = parameters.get(name); String[] newValues = new String[values.length + 1]; System.arraycopy(values, 0, newValues, 0, values.length); newValues[values.length] = value; parameters.put(name, newValues); } else { // No: Add new parameter name / value pair String[] values = new String[] {value}; parameters.put(name, values); } } /** * Includes the selected target.

* * @param context the current JSP page context * @param target the target for the include, might be null * @param element the element to select form the target might be null * @param editable flag to indicate if the target is editable * @param paramMap a map of parameters for the include, will be merged with the request * parameters, might be null * @param attrMap a map of attributes for the include, will be merged with the request * attributes, might be null * @param req the current request * @param res the current response * * @throws JspException in case something goes wrong */ public static void includeTagAction( PageContext context, String target, String element, boolean editable, Map paramMap, Map attrMap, ServletRequest req, ServletResponse res) throws JspException { // no locale and no cachable parameter are used by default includeTagAction(context, target, element, null, editable, true, paramMap, attrMap, req, res); } /** * Includes the selected target.

* * @param context the current JSP page context * @param target the target for the include, might be null * @param element the element to select form the target, might be null * @param locale the locale to use for the selected element, might be null * @param editable flag to indicate if the target is editable * @param cacheable flag to indicate if the target should be cacheable in the Flex cache * @param paramMap a map of parameters for the include, will be merged with the request * parameters, might be null * @param attrMap a map of attributes for the include, will be merged with the request * attributes, might be null * @param req the current request * @param res the current response * * @throws JspException in case something goes wrong */ public static void includeTagAction( PageContext context, String target, String element, Locale locale, boolean editable, boolean cacheable, Map paramMap, Map attrMap, ServletRequest req, ServletResponse res) throws JspException { // the Flex controller provides access to the internal OpenCms structures CmsFlexController controller = CmsFlexController.getController(req); if (target == null) { // set target to default target = controller.getCmsObject().getRequestContext().getUri(); } // resolve possible relative URI target = CmsLinkManager.getAbsoluteUri(target, controller.getCurrentRequest().getElementUri()); try { // check if the target actually exists in the OpenCms VFS controller.getCmsObject().readResource(target); } catch (CmsException e) { // store exception in controller and discontinue controller.setThrowable(e, target); throw new JspException(e); } // include direct edit "start" element (if enabled) boolean directEditOpen = editable && CmsJspTagEditable.startDirectEdit(context, new CmsDirectEditParams(target, element)); // save old parameters from request Map oldParameterMap = CmsCollectionsGenericWrapper.map(req.getParameterMap()); try { // each include will have it's unique map of parameters Map parameterMap = (paramMap == null) ? new HashMap() : new HashMap(paramMap); if (cacheable && (element != null)) { // add template element selector for JSP templates (only required if cacheable) addParameter(parameterMap, I_CmsResourceLoader.PARAMETER_ELEMENT, element, true); } // add parameters to set the correct element controller.getCurrentRequest().addParameterMap(parameterMap); // each include will have it's unique map of attributes Map attributeMap = (attrMap == null) ? new HashMap() : new HashMap(attrMap); // add attributes to set the correct element controller.getCurrentRequest().addAttributeMap(attributeMap); Set dynamicParams = controller.getCurrentRequest().getDynamicParameters(); Map extendedParameterMap = null; if (!dynamicParams.isEmpty()) { // We want to store the parameters from the request with keys in dynamicParams in the flex response's include list, but only if they're set extendedParameterMap = Maps.newHashMap(); extendedParameterMap.putAll(parameterMap); for (String dynamicParam : dynamicParams) { String[] val = req.getParameterMap().get(dynamicParam); if (val != null) { extendedParameterMap.put(dynamicParam, val); } } } if (cacheable) { // use include with cache includeActionWithCache( controller, context, target, extendedParameterMap != null ? extendedParameterMap : parameterMap, attributeMap, req, res); } else { // no cache required includeActionNoCache(controller, context, target, element, locale, req, res); } } finally { // restore old parameter map (if required) if (oldParameterMap != null) { controller.getCurrentRequest().setParameterMap(oldParameterMap); } } // include direct edit "end" element (if required) if (directEditOpen) { CmsJspTagEditable.endDirectEdit(context); } } /** * Includes the selected target without caching.

* * @param controller the current JSP controller * @param context the current JSP page context * @param target the target for the include * @param element the element to select form the target * @param locale the locale to select from the target * @param req the current request * @param res the current response * * @throws JspException in case something goes wrong */ private static void includeActionNoCache( CmsFlexController controller, PageContext context, String target, String element, Locale locale, ServletRequest req, ServletResponse res) throws JspException { try { // include is not cachable CmsFile file = controller.getCmsObject().readFile(target); CmsObject cms = controller.getCmsObject(); if (locale == null) { locale = cms.getRequestContext().getLocale(); } // get the loader for the requested file I_CmsResourceLoader loader = OpenCms.getResourceManager().getLoader(file); String content; if (loader instanceof I_CmsResourceStringDumpLoader) { // loader can provide content as a String I_CmsResourceStringDumpLoader strLoader = (I_CmsResourceStringDumpLoader)loader; content = strLoader.dumpAsString(cms, file, element, locale, req, res); } else { if (!(req instanceof HttpServletRequest) || !(res instanceof HttpServletResponse)) { // http type is required for loader (no refactoring to avoid changes to interface) CmsLoaderException e = new CmsLoaderException( Messages.get().container(Messages.ERR_BAD_REQUEST_RESPONSE_0)); throw new JspException(e); } // get the bytes from the loader and convert them to a String byte[] result = loader.dump( cms, file, element, locale, (HttpServletRequest)req, (HttpServletResponse)res); String encoding; if (loader instanceof CmsJspLoader) { // in case of JSPs use the response encoding if (res instanceof CmsFlexResponse) { encoding = ((CmsFlexResponse)res).getEncoding(); } else { encoding = res.getCharacterEncoding(); } } else { // use the encoding from the property or the system default if not available encoding = cms.readPropertyObject( file, CmsPropertyDefinition.PROPERTY_CONTENT_ENCODING, true).getValue(OpenCms.getSystemInfo().getDefaultEncoding()); } // If the included target issued a redirect null will be returned from loader if (result == null) { result = new byte[0]; } content = new String(result, encoding); } // write the content String to the JSP output writer context.getOut().print(content); } catch (ServletException e) { // store original Exception in controller in order to display it later Throwable t = (e.getRootCause() != null) ? e.getRootCause() : e; t = controller.setThrowable(t, target); throw new JspException(t); } catch (IOException e) { // store original Exception in controller in order to display it later Throwable t = controller.setThrowable(e, target); throw new JspException(t); } catch (CmsException e) { // store original Exception in controller in order to display it later Throwable t = controller.setThrowable(e, target); throw new JspException(t); } } /** * Includes the selected target using the Flex cache.

* * @param controller the current JSP controller * @param context the current JSP page context * @param target the target for the include, might be null * @param parameterMap a map of parameters for the include * @param attributeMap a map of request attributes for the include * @param req the current request * @param res the current response * * @throws JspException in case something goes wrong */ private static void includeActionWithCache( CmsFlexController controller, PageContext context, String target, Map parameterMap, Map attributeMap, ServletRequest req, ServletResponse res) throws JspException { try { // add the target to the include list (the list will be initialized if it is currently empty) controller.getCurrentResponse().addToIncludeList(target, parameterMap, attributeMap); // now use the Flex dispatcher to include the target (this will also work for targets in the OpenCms VFS) try { controller.getCurrentRequest().getRequestDispatcher(target).include(req, res); } finally { // write out a FLEX_CACHE_DELIMITER char on the page, this is used as a parsing delimiter later context.getOut().print(CmsFlexResponse.FLEX_CACHE_DELIMITER); } } catch (ServletException e) { // store original Exception in controller in order to display it later Throwable t = (e.getRootCause() != null) ? e.getRootCause() : e; t = controller.setThrowable(t, target); throw new JspException(t); } catch (IOException e) { // store original Exception in controller in order to display it later Throwable t = controller.setThrowable(e, target); throw new JspException(t); } } /** * This methods adds parameters to the current request.

* * Parameters added here will be treated like parameters from the * HttpRequest on included pages.

* * Remember that the value for a parameter in a HttpRequest is a * String array, not just a simple String. If a parameter added here does * not already exist in the HttpRequest, it will be added. If a parameter * exists, another value will be added to the array of values. If the * value already exists for the parameter, nothing will be added, since a * value can appear only once per parameter.

* * @param name the name to add * @param value the value to add * @see org.opencms.jsp.I_CmsJspTagParamParent#addParameter(String, String) */ public void addParameter(String name, String value) { // No null values allowed in parameters if ((name == null) || (value == null)) { return; } // Check if internal map exists, create new one if not if (m_parameterMap == null) { m_parameterMap = new HashMap(); } addParameter(m_parameterMap, name, value, false); } /** * @return EVAL_PAGE * * @see javax.servlet.jsp.tagext.Tag#doEndTag() * * @throws JspException by interface default */ @Override public int doEndTag() throws JspException { ServletRequest req = pageContext.getRequest(); ServletResponse res = pageContext.getResponse(); if (CmsFlexController.isCmsRequest(req)) { // this will always be true if the page is called through OpenCms CmsObject cms = CmsFlexController.getCmsObject(req); String target = null; // try to find out what to do if (m_target != null) { // option 1: target is set with "page" or "file" parameter target = m_target + getSuffix(); } else if (m_property != null) { // option 2: target is set with "property" parameter try { String prop = cms.readPropertyObject(cms.getRequestContext().getUri(), m_property, true).getValue(); if (prop != null) { target = prop + getSuffix(); } } catch (RuntimeException e) { // target must be null target = null; } catch (Exception e) { // target will be null e = null; } } else if (m_attribute != null) { // option 3: target is set in "attribute" parameter try { String attr = (String)req.getAttribute(m_attribute); if (attr != null) { target = attr + getSuffix(); } } catch (RuntimeException e) { // target must be null target = null; } catch (Exception e) { // target will be null e = null; } } else { // option 4: target might be set in body String body = null; if (getBodyContent() != null) { body = getBodyContent().getString(); if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(body)) { // target IS set in body target = body + getSuffix(); } // else target is not set at all, default will be used } } // now perform the include action includeTagAction( pageContext, target, m_element, null, m_editable, m_cacheable, m_parameterMap, CmsRequestUtil.getAtrributeMap(req), req, res); release(); } return EVAL_PAGE; } /** * Returns {@link #EVAL_BODY_BUFFERED}.

* * @return {@link #EVAL_BODY_BUFFERED} * * @see javax.servlet.jsp.tagext.Tag#doStartTag() */ @Override public int doStartTag() { return EVAL_BODY_BUFFERED; } /** * Returns the attribute.

* * @return the attribute */ public String getAttribute() { return m_attribute != null ? m_attribute : ""; } /** * Returns the cacheable flag.

* * @return the cacheable flag */ public String getCacheable() { return String.valueOf(m_cacheable); } /** * Returns the editable flag.

* * @return the editable flag */ public String getEditable() { return String.valueOf(m_editable); } /** * Returns the element.

* * @return the element */ public String getElement() { return m_element; } /** * Returns the value of {@link #getPage()}.

* * @return the value of {@link #getPage()} * @see #getPage() */ public String getFile() { return getPage(); } /** * Returns the include page target.

* * @return the include page target */ public String getPage() { return m_target != null ? m_target : ""; } /** * Returns the property.

* * @return the property */ public String getProperty() { return m_property != null ? m_property : ""; } /** * Returns the suffix.

* * @return the suffix */ public String getSuffix() { return m_suffix != null ? m_suffix : ""; } /** * @see javax.servlet.jsp.tagext.Tag#release() */ @Override public void release() { super.release(); m_target = null; m_suffix = null; m_property = null; m_element = null; m_parameterMap = null; m_editable = false; m_cacheable = true; } /** * Sets the attribute.

* * @param attribute the attribute to set */ public void setAttribute(String attribute) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(attribute)) { m_attribute = attribute; } } /** * Sets the cacheable flag.

* * Cachable is true by default.

* * @param cacheable the flag to set */ public void setCacheable(String cacheable) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(cacheable)) { m_cacheable = Boolean.valueOf(cacheable).booleanValue(); } } /** * Sets the editable flag.

* * Editable is false by default.

* * @param editable the flag to set */ public void setEditable(String editable) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(editable)) { m_editable = Boolean.valueOf(editable).booleanValue(); } } /** * Sets the element.

* * @param element the element to set */ public void setElement(String element) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(element)) { m_element = element; } } /** * Sets the file, same as using setPage().

* * @param file the file to set * @see #setPage(String) */ public void setFile(String file) { setPage(file); } /** * Sets the include page target.

* * @param target the target to set */ public void setPage(String target) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(target)) { m_target = target; } } /** * Sets the property.

* * @param property the property to set */ public void setProperty(String property) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(property)) { m_property = property; } } /** * Sets the suffix.

* * @param suffix the suffix to set */ public void setSuffix(String suffix) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(suffix)) { m_suffix = suffix.toLowerCase(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy