001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.model.Layout;
020    import com.liferay.portal.kernel.model.Portlet;
021    import com.liferay.portal.kernel.model.PortletApp;
022    import com.liferay.portal.kernel.model.PublicRenderParameter;
023    import com.liferay.portal.kernel.model.User;
024    import com.liferay.portal.kernel.portlet.PortletQNameUtil;
025    import com.liferay.portal.kernel.util.ArrayUtil;
026    import com.liferay.portal.kernel.util.PortalUtil;
027    
028    import java.io.Serializable;
029    
030    import java.util.ArrayList;
031    import java.util.LinkedHashMap;
032    import java.util.List;
033    import java.util.Map;
034    
035    import javax.portlet.Event;
036    import javax.portlet.PortletMode;
037    import javax.portlet.PortletModeException;
038    import javax.portlet.StateAwareResponse;
039    import javax.portlet.WindowState;
040    import javax.portlet.WindowStateException;
041    
042    import javax.servlet.http.HttpServletResponse;
043    
044    import javax.xml.XMLConstants;
045    import javax.xml.namespace.QName;
046    
047    /**
048     * @author Brian Wing Shun Chan
049     */
050    public abstract class StateAwareResponseImpl
051            extends PortletResponseImpl implements StateAwareResponse {
052    
053            public String getDefaultNamespace() {
054                    Portlet portlet = getPortlet();
055    
056                    if (portlet != null) {
057                            return portlet.getPortletApp().getDefaultNamespace();
058                    }
059                    else {
060                            return XMLConstants.NULL_NS_URI;
061                    }
062            }
063    
064            public List<Event> getEvents() {
065                    return _events;
066            }
067    
068            public Layout getLayout() {
069                    return _layout;
070            }
071    
072            @Override
073            public PortletMode getPortletMode() {
074                    return _portletMode;
075            }
076    
077            public String getRedirectLocation() {
078                    return _redirectLocation;
079            }
080    
081            @Override
082            public Map<String, String[]> getRenderParameterMap() {
083                    return _params;
084            }
085    
086            public User getUser() {
087                    return _user;
088            }
089    
090            @Override
091            public WindowState getWindowState() {
092                    return _windowState;
093            }
094    
095            public boolean isCalledSetRenderParameter() {
096                    return _calledSetRenderParameter;
097            }
098    
099            @Override
100            public void removePublicRenderParameter(String name) {
101                    if (name == null) {
102                            throw new IllegalArgumentException();
103                    }
104    
105                    PublicRenderParameter publicRenderParameter =
106                            getPortlet().getPublicRenderParameter(name);
107    
108                    if (publicRenderParameter == null) {
109                            if (_log.isWarnEnabled()) {
110                                    _log.warn("Public parameter " + name + "does not exist");
111                            }
112    
113                            return;
114                    }
115    
116                    com.liferay.portal.kernel.xml.QName qName =
117                            publicRenderParameter.getQName();
118    
119                    String key = PortletQNameUtil.getPublicRenderParameterName(qName);
120    
121                    _publicRenderParameters.remove(key);
122            }
123    
124            @Override
125            public void setEvent(QName name, Serializable value) {
126                    if (name == null) {
127                            throw new IllegalArgumentException();
128                    }
129    
130                    _events.add(new EventImpl(name.getLocalPart(), name, value));
131            }
132    
133            @Override
134            public void setEvent(String name, Serializable value) {
135                    if (name == null) {
136                            throw new IllegalArgumentException();
137                    }
138    
139                    setEvent(new QName(getDefaultNamespace(), name), value);
140            }
141    
142            @Override
143            public void setPortletMode(PortletMode portletMode)
144                    throws PortletModeException {
145    
146                    if (_redirectLocation != null) {
147                            throw new IllegalStateException();
148                    }
149    
150                    if (!_portletRequestImpl.isPortletModeAllowed(portletMode)) {
151                            throw new PortletModeException(portletMode.toString(), portletMode);
152                    }
153    
154                    try {
155                            _portletMode = PortalUtil.updatePortletMode(
156                                    _portletName, _user, _layout, portletMode,
157                                    _portletRequestImpl.getHttpServletRequest());
158    
159                            _portletRequestImpl.setPortletMode(_portletMode);
160                    }
161                    catch (Exception e) {
162                            throw new PortletModeException(e, portletMode);
163                    }
164    
165                    _calledSetRenderParameter = true;
166            }
167    
168            public void setRedirectLocation(String redirectLocation) {
169                    _redirectLocation = redirectLocation;
170            }
171    
172            @Override
173            public void setRenderParameter(String name, String value) {
174                    if (_redirectLocation != null) {
175                            throw new IllegalStateException();
176                    }
177    
178                    if ((name == null) || (value == null)) {
179                            throw new IllegalArgumentException();
180                    }
181    
182                    setRenderParameter(name, new String[] {value});
183            }
184    
185            @Override
186            public void setRenderParameter(String name, String[] values) {
187                    if (_redirectLocation != null) {
188                            throw new IllegalStateException();
189                    }
190    
191                    if ((name == null) || (values == null)) {
192                            throw new IllegalArgumentException();
193                    }
194    
195                    for (int i = 0; i < values.length; i++) {
196                            if (values[i] == null) {
197                                    throw new IllegalArgumentException();
198                            }
199                    }
200    
201                    if (!setPublicRenderParameter(name, values)) {
202                            _params.put(name, values);
203                    }
204    
205                    _calledSetRenderParameter = true;
206            }
207    
208            @Override
209            public void setRenderParameters(Map<String, String[]> params) {
210                    if (_redirectLocation != null) {
211                            throw new IllegalStateException();
212                    }
213    
214                    if (params == null) {
215                            throw new IllegalArgumentException();
216                    }
217                    else {
218                            Map<String, String[]> newParams = new LinkedHashMap<>();
219    
220                            for (Map.Entry<String, String[]> entry : params.entrySet()) {
221                                    String key = entry.getKey();
222                                    String[] value = entry.getValue();
223    
224                                    if (key == null) {
225                                            throw new IllegalArgumentException();
226                                    }
227                                    else if (value == null) {
228                                            throw new IllegalArgumentException();
229                                    }
230    
231                                    if (setPublicRenderParameter(key, value)) {
232                                            continue;
233                                    }
234    
235                                    newParams.put(key, value);
236                            }
237    
238                            _params = newParams;
239                    }
240    
241                    _calledSetRenderParameter = true;
242            }
243    
244            @Override
245            public void setWindowState(WindowState windowState)
246                    throws WindowStateException {
247    
248                    if (_redirectLocation != null) {
249                            throw new IllegalStateException();
250                    }
251    
252                    if (!_portletRequestImpl.isWindowStateAllowed(windowState)) {
253                            throw new WindowStateException(windowState.toString(), windowState);
254                    }
255    
256                    try {
257                            _windowState = PortalUtil.updateWindowState(
258                                    _portletName, _user, _layout, windowState,
259                                    _portletRequestImpl.getHttpServletRequest());
260    
261                            _portletRequestImpl.setWindowState(_windowState);
262                    }
263                    catch (Exception e) {
264                            throw new WindowStateException(e, windowState);
265                    }
266    
267                    _calledSetRenderParameter = true;
268            }
269    
270            protected void init(
271                            PortletRequestImpl portletRequestImpl, HttpServletResponse response,
272                            String portletName, User user, Layout layout,
273                            WindowState windowState, PortletMode portletMode)
274                    throws PortletModeException, WindowStateException {
275    
276                    super.init(
277                            portletRequestImpl, response, portletName, layout.getCompanyId(),
278                            layout.getPlid());
279    
280                    _portletRequestImpl = portletRequestImpl;
281                    _portletName = portletName;
282                    _user = user;
283                    _layout = layout;
284    
285                    Portlet portlet = portletRequestImpl.getPortlet();
286    
287                    PortletApp portletApp = portlet.getPortletApp();
288    
289                    _publicRenderParameters = PublicRenderParametersPool.get(
290                            getHttpServletRequest(), layout.getPlid(), portletApp.isWARFile());
291    
292                    if (windowState != null) {
293                            setWindowState(windowState);
294                    }
295    
296                    if (portletMode != null) {
297                            setPortletMode(portletMode);
298                    }
299    
300                    // Set _calledSetRenderParameter to false because setWindowState and
301                    // setPortletMode sets it to true
302    
303                    _calledSetRenderParameter = false;
304            }
305    
306            protected void reset() {
307                    _calledSetRenderParameter = false;
308                    _events.clear();
309                    _params.clear();
310                    _portletMode = null;
311                    _redirectLocation = null;
312                    _windowState = null;
313            }
314    
315            protected boolean setPublicRenderParameter(String name, String[] values) {
316                    Portlet portlet = getPortlet();
317    
318                    PublicRenderParameter publicRenderParameter =
319                            portlet.getPublicRenderParameter(name);
320    
321                    if (publicRenderParameter == null) {
322                            return false;
323                    }
324    
325                    com.liferay.portal.kernel.xml.QName qName =
326                            publicRenderParameter.getQName();
327    
328                    String[] oldValues = _publicRenderParameters.get(name);
329    
330                    if (oldValues != null) {
331                            values = ArrayUtil.append(oldValues, values);
332                    }
333    
334                    _publicRenderParameters.put(
335                            PortletQNameUtil.getPublicRenderParameterName(qName), values);
336    
337                    return true;
338            }
339    
340            private static final Log _log = LogFactoryUtil.getLog(
341                    StateAwareResponseImpl.class);
342    
343            private boolean _calledSetRenderParameter;
344            private final List<Event> _events = new ArrayList<>();
345            private Layout _layout;
346            private Map<String, String[]> _params = new LinkedHashMap<>();
347            private PortletMode _portletMode;
348            private String _portletName;
349            private PortletRequestImpl _portletRequestImpl;
350            private Map<String, String[]> _publicRenderParameters;
351            private String _redirectLocation;
352            private User _user;
353            private WindowState _windowState;
354    
355    }