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.portlet.LiferayPortletRequest;
018    import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
019    import com.liferay.portal.kernel.portlet.LiferayPortletURL;
020    import com.liferay.portal.kernel.portlet.LiferayWindowState;
021    import com.liferay.portal.kernel.util.ArrayUtil;
022    import com.liferay.portal.kernel.util.HttpUtil;
023    import com.liferay.portal.kernel.util.ParamUtil;
024    import com.liferay.portal.kernel.util.PropsKeys;
025    import com.liferay.portal.kernel.util.PropsUtil;
026    import com.liferay.portal.kernel.util.StringBundler;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.Validator;
029    import com.liferay.portal.kernel.util.WebKeys;
030    import com.liferay.portal.model.LayoutTypePortlet;
031    import com.liferay.portal.model.Portlet;
032    import com.liferay.portal.theme.ThemeDisplay;
033    import com.liferay.portal.util.PortalUtil;
034    
035    import java.util.Enumeration;
036    import java.util.HashMap;
037    import java.util.Map;
038    
039    import javax.portlet.MimeResponse;
040    import javax.portlet.PortletException;
041    import javax.portlet.PortletMode;
042    import javax.portlet.PortletRequest;
043    import javax.portlet.PortletURL;
044    import javax.portlet.WindowState;
045    
046    import javax.servlet.http.HttpServletRequest;
047    
048    /**
049     * @author Brian Wing Shun Chan
050     * @author Miguel Pastor
051     */
052    public class PortletURLUtil {
053    
054            public static PortletURL clone(
055                            LiferayPortletURL liferayPortletURL, String lifecycle,
056                            LiferayPortletResponse liferayPortletResponse)
057                    throws PortletException {
058    
059                    LiferayPortletURL newLiferayPortletURL =
060                            liferayPortletResponse.createLiferayPortletURL(lifecycle);
061    
062                    newLiferayPortletURL.setPortletId(liferayPortletURL.getPortletId());
063    
064                    WindowState windowState = liferayPortletURL.getWindowState();
065    
066                    if (windowState != null) {
067                            newLiferayPortletURL.setWindowState(windowState);
068                    }
069    
070                    PortletMode portletMode = liferayPortletURL.getPortletMode();
071    
072                    if (portletMode != null) {
073                            newLiferayPortletURL.setPortletMode(portletMode);
074                    }
075    
076                    newLiferayPortletURL.setParameters(liferayPortletURL.getParameterMap());
077    
078                    return newLiferayPortletURL;
079            }
080    
081            public static PortletURL clone(
082                            PortletURL portletURL,
083                            LiferayPortletResponse liferayPortletResponse)
084                    throws PortletException {
085    
086                    LiferayPortletURL liferayPortletURL = (LiferayPortletURL)portletURL;
087    
088                    return clone(
089                            liferayPortletURL, liferayPortletURL.getLifecycle(),
090                            liferayPortletResponse);
091            }
092    
093            public static PortletURL clone(
094                            PortletURL portletURL, MimeResponse mimeResponse)
095                    throws PortletException {
096    
097                    LiferayPortletURL liferayPortletURL = (LiferayPortletURL)portletURL;
098    
099                    return clone(
100                            liferayPortletURL, liferayPortletURL.getLifecycle(),
101                            (LiferayPortletResponse)mimeResponse);
102            }
103    
104            public static PortletURL clone(
105                            PortletURL portletURL, String lifecycle,
106                            LiferayPortletResponse liferayPortletResponse)
107                    throws PortletException {
108    
109                    LiferayPortletURL liferayPortletURL = (LiferayPortletURL)portletURL;
110    
111                    return clone(liferayPortletURL, lifecycle, liferayPortletResponse);
112            }
113    
114            public static PortletURL clone(
115                            PortletURL portletURL, String lifecycle, MimeResponse mimeResponse)
116                    throws PortletException {
117    
118                    LiferayPortletURL liferayPortletURL = (LiferayPortletURL)portletURL;
119    
120                    return clone(
121                            liferayPortletURL, lifecycle, (LiferayPortletResponse)mimeResponse);
122            }
123    
124            public static PortletURL getCurrent(
125                    LiferayPortletRequest liferayPortletRequest,
126                    LiferayPortletResponse liferayPortletResponse) {
127    
128                    PortletURL portletURL = (PortletURL)liferayPortletRequest.getAttribute(
129                            WebKeys.CURRENT_PORTLET_URL);
130    
131                    if (portletURL != null) {
132                            return portletURL;
133                    }
134    
135                    portletURL = liferayPortletResponse.createRenderURL();
136    
137                    Enumeration<String> enu = liferayPortletRequest.getParameterNames();
138    
139                    while (enu.hasMoreElements()) {
140                            String param = enu.nextElement();
141                            String[] values = liferayPortletRequest.getParameterValues(param);
142    
143                            boolean addParam = true;
144    
145                            // Don't set paramter values that are over 32 kb. See LEP-1755.
146    
147                            for (int i = 0; i < values.length; i++) {
148                                    if (values[i].length() > _CURRENT_URL_PARAMETER_THRESHOLD) {
149                                            addParam = false;
150    
151                                            break;
152                                    }
153                            }
154    
155                            if (addParam) {
156                                    portletURL.setParameter(param, values);
157                            }
158                    }
159    
160                    liferayPortletRequest.setAttribute(
161                            WebKeys.CURRENT_PORTLET_URL, portletURL);
162    
163                    return portletURL;
164            }
165    
166            public static PortletURL getCurrent(
167                    PortletRequest portletRequest, MimeResponse mimeResponse) {
168    
169                    return getCurrent(
170                            (LiferayPortletRequest)portletRequest,
171                            (LiferayPortletResponse)mimeResponse);
172            }
173    
174            public static String getRefreshURL(
175                    HttpServletRequest request, ThemeDisplay themeDisplay) {
176    
177                    return getRefreshURL(request, themeDisplay, true);
178            }
179    
180            public static String getRefreshURL(
181                    HttpServletRequest request, ThemeDisplay themeDisplay,
182                    boolean includeParameters) {
183    
184                    StringBundler sb = new StringBundler(34);
185    
186                    sb.append(themeDisplay.getPathMain());
187                    sb.append("/portal/render_portlet?p_l_id=");
188    
189                    long plid = themeDisplay.getPlid();
190    
191                    sb.append(plid);
192    
193                    Portlet portlet = (Portlet)request.getAttribute(WebKeys.RENDER_PORTLET);
194    
195                    String portletId = portlet.getPortletId();
196    
197                    sb.append("&p_p_id=");
198                    sb.append(portletId);
199    
200                    sb.append("&p_p_lifecycle=0&p_t_lifecycle=");
201                    sb.append(themeDisplay.getLifecycle());
202    
203                    WindowState windowState = WindowState.NORMAL;
204    
205                    if (themeDisplay.isStatePopUp()) {
206                            windowState = LiferayWindowState.POP_UP;
207                    }
208                    else {
209                            LayoutTypePortlet layoutTypePortlet =
210                                    themeDisplay.getLayoutTypePortlet();
211    
212                            if (layoutTypePortlet.hasStateMaxPortletId(portletId)) {
213                                    windowState = WindowState.MAXIMIZED;
214                            }
215                            else if (layoutTypePortlet.hasStateMinPortletId(portletId)) {
216                                    windowState = WindowState.MINIMIZED;
217                            }
218                    }
219    
220                    sb.append("&p_p_state=");
221                    sb.append(windowState);
222    
223                    sb.append("&p_p_mode=view&p_p_col_id=");
224    
225                    String columnId = (String)request.getAttribute(
226                            WebKeys.RENDER_PORTLET_COLUMN_ID);
227    
228                    sb.append(columnId);
229    
230                    Integer columnPos = (Integer)request.getAttribute(
231                            WebKeys.RENDER_PORTLET_COLUMN_POS);
232    
233                    sb.append("&p_p_col_pos=");
234                    sb.append(columnPos);
235    
236                    Integer columnCount = (Integer)request.getAttribute(
237                            WebKeys.RENDER_PORTLET_COLUMN_COUNT);
238    
239                    sb.append("&p_p_col_count=");
240                    sb.append(columnCount);
241    
242                    if (portlet.isStatic()) {
243                            sb.append("&p_p_static=1");
244    
245                            if (portlet.isStaticStart()) {
246                                    sb.append("&p_p_static_start=1");
247                            }
248                    }
249    
250                    sb.append("&p_p_isolated=1");
251    
252                    long sourceGroupId = ParamUtil.getLong(request, "p_v_l_s_g_id");
253    
254                    if (sourceGroupId > 0) {
255                            sb.append("&p_v_l_s_g_id=");
256                            sb.append(sourceGroupId);
257                    }
258    
259                    String doAsUserId = themeDisplay.getDoAsUserId();
260    
261                    if (Validator.isNotNull(doAsUserId)) {
262                            sb.append("&doAsUserId=");
263                            sb.append(HttpUtil.encodeURL(doAsUserId));
264                    }
265    
266                    String currentURL = PortalUtil.getCurrentURL(request);
267    
268                    sb.append("&currentURL=");
269                    sb.append(HttpUtil.encodeURL(currentURL));
270    
271                    String ppid = ParamUtil.getString(request, "p_p_id");
272    
273                    if (!ppid.equals(portletId)) {
274                            return sb.toString();
275                    }
276    
277                    String settingsScope = (String)request.getAttribute(
278                            WebKeys.SETTINGS_SCOPE);
279    
280                    settingsScope = ParamUtil.get(request, "settingsScope", settingsScope);
281    
282                    if (Validator.isNotNull(settingsScope)) {
283                            sb.append("&settingsScope=");
284                            sb.append(settingsScope);
285                    }
286    
287                    if (includeParameters) {
288                            Map<String, String[]> parameters = getRefreshURLParameters(request);
289    
290                            for (Map.Entry<String, String[]> entry : parameters.entrySet()) {
291                                    String name = entry.getKey();
292                                    String[] values = entry.getValue();
293    
294                                    for (int i = 0; i < values.length; i++) {
295                                            sb.append(StringPool.AMPERSAND);
296                                            sb.append(name);
297                                            sb.append(StringPool.EQUAL);
298                                            sb.append(HttpUtil.encodeURL(values[i]));
299                                    }
300                            }
301                    }
302    
303                    return sb.toString();
304            }
305    
306            public static Map<String, String[]> getRefreshURLParameters(
307                    HttpServletRequest request) {
308    
309                    Map<String, String[]> refreshURLParameters = new HashMap<>();
310    
311                    String ppid = ParamUtil.getString(request, "p_p_id");
312    
313                    Portlet portlet = (Portlet)request.getAttribute(WebKeys.RENDER_PORTLET);
314    
315                    if (ppid.equals(portlet.getPortletId())) {
316                            String namespace = PortalUtil.getPortletNamespace(
317                                    portlet.getPortletId());
318    
319                            Map<String, String[]> parameters = request.getParameterMap();
320    
321                            for (Map.Entry<String, String[]> entry : parameters.entrySet()) {
322                                    String name = entry.getKey();
323    
324                                    if (name.startsWith(StringPool.UNDERLINE) &&
325                                            !name.startsWith(namespace)) {
326    
327                                            continue;
328                                    }
329    
330                                    if (!PortalUtil.isReservedParameter(name) &&
331                                            !name.equals("currentURL") &&
332                                            !name.equals("settingsScope") &&
333                                            !isRefreshURLReservedParameter(name, namespace)) {
334    
335                                            String[] values = entry.getValue();
336    
337                                            if (values == null) {
338                                                    continue;
339                                            }
340    
341                                            refreshURLParameters.put(name, values);
342                                    }
343                            }
344                    }
345    
346                    return refreshURLParameters;
347            }
348    
349            protected static boolean isRefreshURLReservedParameter(
350                    String parameter, String namespace) {
351    
352                    if (ArrayUtil.isEmpty(_PORTLET_URL_REFRESH_URL_RESERVED_PARAMETERS)) {
353                            return false;
354                    }
355    
356                    for (String reservedParameter :
357                                    _PORTLET_URL_REFRESH_URL_RESERVED_PARAMETERS) {
358    
359                            if (parameter.equals(reservedParameter) ||
360                                    parameter.equals(namespace.concat(reservedParameter))) {
361    
362                                    return true;
363                            }
364                    }
365    
366                    return false;
367            }
368    
369            private static final int _CURRENT_URL_PARAMETER_THRESHOLD = 32768;
370    
371            private static final String[] _PORTLET_URL_REFRESH_URL_RESERVED_PARAMETERS =
372                    PropsUtil.getArray(
373                            PropsKeys.PORTLET_URL_REFRESH_URL_RESERVED_PARAMETERS);
374    
375    }