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.flex.CmsFlexController;
031import org.opencms.flex.CmsFlexRequest;
032import org.opencms.main.CmsLog;
033
034import java.util.Collections;
035import java.util.Map;
036import java.util.Set;
037
038import javax.servlet.http.HttpServletRequest;
039import javax.servlet.jsp.tagext.TagSupport;
040import javax.servlet.jsp.tagext.TryCatchFinally;
041
042import org.apache.commons.logging.Log;
043
044import com.google.common.collect.Maps;
045import com.google.common.collect.Sets;
046
047/**
048 * This tag is used to dynamically add request parameters which are available during the execution of its body.<p>
049 * Request parameters are added with the &lt;cms:param&gt; tag.
050 */
051public class CmsJspTagAddParams extends TagSupport implements I_CmsJspTagParamParent, TryCatchFinally {
052
053    /**
054     * Keeps track of the runtime state of a single execution of this tag.<p>
055     */
056    public static class ParamState {
057
058        /** The running request. */
059        private CmsFlexRequest m_request;
060
061        /** The original set of parameters. */
062        private Map<String, String[]> m_savedParams;
063
064        /** The saved set of dynamic parameters. */
065        private Set<String> m_savedDynamicParams;
066
067        /**
068         * Creates a new instance.<p>
069         *
070         * @param request the current request
071         */
072        public ParamState(CmsFlexRequest request) {
073            m_request = request;
074        }
075
076        /**
077         * Adds a request parameter.<p>
078         *
079         * @param key the parameter name
080         * @param value the parameter value
081         */
082        public void addParameter(String key, String value) {
083
084            m_request.addParameterMap(Collections.singletonMap(key, new String[] {value}));
085            m_request.getDynamicParameters().add(key);
086        }
087
088        /**
089         * Initializes the tag state and sets a new parameter map on the request for which it was instantiated.<p>
090         */
091        public void init() {
092
093            m_savedParams = m_request.getParameterMap();
094            m_savedDynamicParams = m_request.getDynamicParameters();
095            Map<String, String[]> params = Maps.newHashMap();
096            if (m_savedParams != null) {
097                params.putAll(m_savedParams);
098            }
099            m_request.setParameterMap(params);
100            Set<String> dynamicParams = Sets.newHashSet(m_savedDynamicParams);
101            m_request.setDynamicParameters(dynamicParams);
102        }
103
104        /**
105         * Restores the original set of parameters.<p>
106         */
107        public void undoChanges() {
108
109            m_request.setParameterMap(m_savedParams);
110            m_request.setDynamicParameters(m_savedDynamicParams);
111        }
112
113    }
114
115    /** Logger instance for this class. */
116    private static final Log LOG = CmsLog.getLog(CmsJspTagAddParams.class);
117
118    /** Serial version id. */
119    private static final long serialVersionUID = 1L;
120
121    /** The current state. */
122    private ParamState m_state;
123
124    /**
125     * @see org.opencms.jsp.I_CmsJspTagParamParent#addParameter(java.lang.String, java.lang.String)
126     */
127    public void addParameter(String name, String value) {
128
129        if (m_state != null) {
130            m_state.addParameter(name, value);
131        }
132    }
133
134    /**
135     * @see javax.servlet.jsp.tagext.TryCatchFinally#doCatch(java.lang.Throwable)
136     */
137    public void doCatch(Throwable t) throws Throwable {
138
139        throw t;
140    }
141
142    /**
143     * @see javax.servlet.jsp.tagext.TryCatchFinally#doFinally()
144     */
145    public void doFinally() {
146
147        clearState();
148    }
149
150    /**
151     * @see javax.servlet.jsp.tagext.TagSupport#doStartTag()
152     */
153    @Override
154    public int doStartTag() {
155
156        HttpServletRequest request = (HttpServletRequest)(pageContext.getRequest());
157        if (CmsFlexController.isCmsRequest(request)) {
158            CmsFlexController controller = CmsFlexController.getController(request);
159            m_state = new ParamState(controller.getCurrentRequest());
160            m_state.init();
161        } else {
162            LOG.error("Using <cms:addparams> tag outside of a Flex request");
163        }
164        return EVAL_BODY_INCLUDE;
165    }
166
167    /**
168     * Clears the tag state if it is set, and restores the previous set of parameters.<p>
169     */
170    private void clearState() {
171
172        if (m_state != null) {
173            ParamState state = m_state;
174            m_state = null;
175            state.undoChanges();
176        }
177    }
178
179}