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