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.taglib.portletext;
016    
017    import com.liferay.portal.kernel.json.JSONFactoryUtil;
018    import com.liferay.portal.kernel.json.JSONObject;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.portlet.PortletContainerUtil;
022    import com.liferay.portal.kernel.portlet.PortletJSONUtil;
023    import com.liferay.portal.kernel.portlet.PortletLayoutListener;
024    import com.liferay.portal.kernel.portlet.PortletParameterUtil;
025    import com.liferay.portal.kernel.portlet.PortletProvider;
026    import com.liferay.portal.kernel.portlet.PortletProviderUtil;
027    import com.liferay.portal.kernel.portlet.RestrictPortletServletRequest;
028    import com.liferay.portal.kernel.servlet.DynamicServletRequest;
029    import com.liferay.portal.kernel.util.MapUtil;
030    import com.liferay.portal.kernel.util.PrefixPredicateFilter;
031    import com.liferay.portal.kernel.util.StringPool;
032    import com.liferay.portal.kernel.util.Validator;
033    import com.liferay.portal.kernel.util.WebKeys;
034    import com.liferay.portal.model.Layout;
035    import com.liferay.portal.model.LayoutTypePortlet;
036    import com.liferay.portal.model.Portlet;
037    import com.liferay.portal.model.PortletInstance;
038    import com.liferay.portal.model.PortletPreferencesIds;
039    import com.liferay.portal.security.permission.ActionKeys;
040    import com.liferay.portal.service.PortletLocalServiceUtil;
041    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
042    import com.liferay.portal.service.permission.LayoutPermissionUtil;
043    import com.liferay.portal.theme.ThemeDisplay;
044    import com.liferay.portal.util.PortalUtil;
045    import com.liferay.portal.util.PortletKeys;
046    import com.liferay.portlet.PortletPreferencesFactoryConstants;
047    import com.liferay.portlet.PortletPreferencesFactoryUtil;
048    import com.liferay.taglib.servlet.PipingServletResponse;
049    import com.liferay.taglib.util.PortalIncludeUtil;
050    
051    import java.util.Map;
052    
053    import javax.portlet.PortletPreferences;
054    
055    import javax.servlet.http.HttpServletRequest;
056    import javax.servlet.http.HttpServletResponse;
057    import javax.servlet.jsp.JspException;
058    import javax.servlet.jsp.PageContext;
059    import javax.servlet.jsp.tagext.TagSupport;
060    
061    /**
062     * @author Brian Wing Shun Chan
063     */
064    public class RuntimeTag extends TagSupport {
065    
066            public static void doTag(
067                            String portletName, PageContext pageContext,
068                            HttpServletRequest request, HttpServletResponse response)
069                    throws Exception {
070    
071                    doTag(portletName, null, pageContext, request, response);
072            }
073    
074            public static void doTag(
075                            String portletProviderClassName,
076                            PortletProvider.Action portletProviderAction, String instanceId,
077                            String queryString, String defaultPreferences,
078                            PageContext pageContext, HttpServletRequest request,
079                            HttpServletResponse response)
080                    throws Exception {
081    
082                    String portletId = PortletProviderUtil.getPortletId(
083                            portletProviderClassName, portletProviderAction);
084    
085                    if (Validator.isNotNull(portletId)) {
086                            doTag(
087                                    portletId, instanceId, queryString, _SETTINGS_SCOPE_DEFAULT,
088                                    defaultPreferences, pageContext, request, response);
089                    }
090                    else {
091                            ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
092                                    WebKeys.THEME_DISPLAY);
093    
094                            Layout layout = themeDisplay.getLayout();
095    
096                            if (!layout.isTypeControlPanel() &&
097                                    !LayoutPermissionUtil.contains(
098                                            themeDisplay.getPermissionChecker(), layout,
099                                            ActionKeys.UPDATE)) {
100    
101                                    return;
102                            }
103    
104                            request.setAttribute(
105                                    "liferay-portlet:runtime:portletProviderClassName",
106                                    portletProviderClassName);
107                            request.setAttribute(
108                                    "liferay-portlet:runtime:portletProviderAction",
109                                    portletProviderAction);
110    
111                            PortalIncludeUtil.include(pageContext, _ERROR_PAGE);
112                    }
113            }
114    
115            public static void doTag(
116                            String portletName, String queryString, PageContext pageContext,
117                            HttpServletRequest request, HttpServletResponse response)
118                    throws Exception {
119    
120                    doTag(portletName, queryString, null, pageContext, request, response);
121            }
122    
123            public static void doTag(
124                            String portletName, String queryString, String defaultPreferences,
125                            PageContext pageContext, HttpServletRequest request,
126                            HttpServletResponse response)
127                    throws Exception {
128    
129                    doTag(
130                            portletName, StringPool.BLANK, queryString, _SETTINGS_SCOPE_DEFAULT,
131                            defaultPreferences, pageContext, request, response);
132            }
133    
134            public static void doTag(
135                            String portletName, String instanceId, String queryString,
136                            String defaultPreferences, PageContext pageContext,
137                            HttpServletRequest request, HttpServletResponse response)
138                    throws Exception {
139    
140                    doTag(
141                            portletName, instanceId, queryString, _SETTINGS_SCOPE_DEFAULT,
142                            defaultPreferences, pageContext, request, response);
143            }
144    
145            public static void doTag(
146                            String portletName, String instanceId, String queryString,
147                            String settingsScope, String defaultPreferences,
148                            PageContext pageContext, HttpServletRequest request,
149                            HttpServletResponse response)
150                    throws Exception {
151    
152                    if (pageContext != null) {
153                            response = new PipingServletResponse(
154                                    response, pageContext.getOut());
155                    }
156    
157                    PortletInstance portletInstance =
158                            PortletInstance.fromPortletInstanceKey(portletName);
159    
160                    if (Validator.isNotNull(instanceId)) {
161                            portletInstance = new PortletInstance(
162                                    portletInstance.getPortletName(), portletInstance.getUserId(),
163                                    instanceId);
164                    }
165    
166                    RestrictPortletServletRequest restrictPortletServletRequest =
167                            new RestrictPortletServletRequest(
168                                    PortalUtil.getOriginalServletRequest(request));
169    
170                    queryString = PortletParameterUtil.addNamespace(
171                            portletInstance.getPortletInstanceKey(), queryString);
172    
173                    Map<String, String[]> parameterMap = request.getParameterMap();
174    
175                    if (!Validator.equals(
176                                    portletInstance.getPortletInstanceKey(),
177                                    request.getParameter("p_p_id"))) {
178    
179                            parameterMap = MapUtil.filterByKeys(
180                                    parameterMap, new PrefixPredicateFilter("p_p_"));
181                    }
182    
183                    request = DynamicServletRequest.addQueryString(
184                            restrictPortletServletRequest, parameterMap, queryString, false);
185    
186                    try {
187                            request.setAttribute(WebKeys.RENDER_PORTLET_RESOURCE, Boolean.TRUE);
188    
189                            ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
190                                    WebKeys.THEME_DISPLAY);
191    
192                            if (themeDisplay.isStateMaximized()) {
193                                    LayoutTypePortlet layoutTypePortlet =
194                                            themeDisplay.getLayoutTypePortlet();
195    
196                                    if (layoutTypePortlet.hasStateMaxPortletId(
197                                                    portletInstance.getPortletInstanceKey())) {
198    
199                                            // A portlet in the maximized state has already been
200                                            // processed
201    
202                                            return;
203                                    }
204                            }
205    
206                            Layout layout = themeDisplay.getLayout();
207    
208                            Portlet portlet = getPortlet(
209                                    themeDisplay.getCompanyId(),
210                                    portletInstance.getPortletInstanceKey());
211    
212                            PortletPreferences renderPortletPreferences =
213                                    getRenderPortletPreferences(
214                                            themeDisplay, settingsScope, portlet, defaultPreferences);
215    
216                            if (renderPortletPreferences != null) {
217                                    request.setAttribute(
218                                            WebKeys.RENDER_PORTLET_PREFERENCES,
219                                            renderPortletPreferences);
220                            }
221    
222                            request.setAttribute(WebKeys.SETTINGS_SCOPE, settingsScope);
223    
224                            JSONObject jsonObject = null;
225    
226                            if ((PortletPreferencesLocalServiceUtil.getPortletPreferencesCount(
227                                            PortletKeys.PREFS_OWNER_TYPE_LAYOUT, themeDisplay.getPlid(),
228                                            portletInstance.getPortletInstanceKey()) < 1) ||
229                                    layout.isTypeControlPanel() || layout.isTypePanel()) {
230    
231                                    PortletPreferencesFactoryUtil.getLayoutPortletSetup(
232                                            layout, portletInstance.getPortletInstanceKey(),
233                                            defaultPreferences);
234                                    PortletPreferencesFactoryUtil.getPortletSetup(
235                                            request, portletInstance.getPortletInstanceKey(),
236                                            defaultPreferences);
237    
238                                    PortletLayoutListener portletLayoutListener =
239                                            portlet.getPortletLayoutListenerInstance();
240    
241                                    if (portletLayoutListener != null) {
242                                            portletLayoutListener.onAddToLayout(
243                                                    portletInstance.getPortletInstanceKey(),
244                                                    themeDisplay.getPlid());
245                                    }
246    
247                                    jsonObject = JSONFactoryUtil.createJSONObject();
248    
249                                    PortletJSONUtil.populatePortletJSONObject(
250                                            request, StringPool.BLANK, portlet, jsonObject);
251                            }
252    
253                            if (jsonObject != null) {
254                                    PortletJSONUtil.writeHeaderPaths(response, jsonObject);
255                            }
256    
257                            PortletContainerUtil.render(request, response, portlet);
258    
259                            if (jsonObject != null) {
260                                    PortletJSONUtil.writeFooterPaths(response, jsonObject);
261                            }
262                    }
263                    finally {
264                            restrictPortletServletRequest.mergeSharedAttributes();
265                    }
266            }
267    
268            @Override
269            public int doEndTag() throws JspException {
270                    try {
271                            HttpServletRequest request =
272                                    (HttpServletRequest)pageContext.getRequest();
273    
274                            Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
275    
276                            if (layout == null) {
277                                    return EVAL_PAGE;
278                            }
279    
280                            HttpServletResponse response =
281                                    (HttpServletResponse)pageContext.getResponse();
282    
283                            if (Validator.isNotNull(_portletProviderClassName) &&
284                                    (_portletProviderAction != null)) {
285                                            doTag(
286                                                    _portletProviderClassName, _portletProviderAction,
287                                                    _instanceId, _queryString, _defaultPreferences,
288                                                    pageContext, request, response);
289                            }
290                            else {
291                                    doTag(
292                                            _portletName, _instanceId, _queryString, _settingsScope,
293                                            _defaultPreferences, pageContext, request, response);
294                            }
295    
296                            return EVAL_PAGE;
297                    }
298                    catch (Exception e) {
299                            _log.error(e, e);
300    
301                            throw new JspException(e);
302                    }
303            }
304    
305            public void setDefaultPreferences(String defaultPreferences) {
306                    _defaultPreferences = defaultPreferences;
307            }
308    
309            public void setInstanceId(String instanceId) {
310                    _instanceId = instanceId;
311            }
312    
313            public void setPortletName(String portletName) {
314                    _portletName = portletName;
315            }
316    
317            public void setPortletProviderAction(
318                    PortletProvider.Action portletProviderAction) {
319    
320                    _portletProviderAction = portletProviderAction;
321            }
322    
323            public void setPortletProviderClassName(String portletProviderClassName) {
324                    _portletProviderClassName = portletProviderClassName;
325            }
326    
327            public void setQueryString(String queryString) {
328                    _queryString = queryString;
329            }
330    
331            public void setSettingsScope(String settingsScope) {
332                    _settingsScope = settingsScope;
333            }
334    
335            /**
336             * @see com.liferay.portal.model.impl.LayoutTypePortletImpl#getStaticPortlets(
337             *      String)
338             */
339            protected static Portlet getPortlet(long companyId, String portletId)
340                    throws Exception {
341    
342                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
343                            companyId, portletId);
344    
345                    // See LayoutTypePortletImpl#getStaticPortlets for why we only clone
346                    // non-instanceable portlets
347    
348                    if (!portlet.isInstanceable()) {
349                            portlet = (Portlet)portlet.clone();
350                    }
351    
352                    portlet.setStatic(true);
353    
354                    return portlet;
355            }
356    
357            protected static PortletPreferences getRenderPortletPreferences(
358                    ThemeDisplay themeDisplay, String settingsScope, Portlet portlet,
359                    String defaultPreferences) {
360    
361                    PortletPreferencesIds portletPreferencesIds =
362                            PortletPreferencesFactoryUtil.getPortletPreferencesIds(
363                                    themeDisplay.getCompanyId(), themeDisplay.getSiteGroupId(),
364                                    themeDisplay.getPlid(), portlet.getPortletId(), settingsScope);
365    
366                    if (PortletPreferencesLocalServiceUtil.getPortletPreferencesCount(
367                                    portletPreferencesIds.getOwnerId(),
368                                    portletPreferencesIds.getOwnerType(),
369                                    portletPreferencesIds.getPlid(), portlet, true) > 0) {
370    
371                            return PortletPreferencesLocalServiceUtil.getPreferences(
372                                    themeDisplay.getCompanyId(), portletPreferencesIds.getOwnerId(),
373                                    portletPreferencesIds.getOwnerType(),
374                                    portletPreferencesIds.getPlid(), portlet.getPortletId());
375                    }
376    
377                    if (Validator.isNotNull(defaultPreferences)) {
378                            return PortletPreferencesFactoryUtil.fromDefaultXML(
379                                    defaultPreferences);
380                    }
381    
382                    return null;
383            }
384    
385            private static final String _ERROR_PAGE =
386                    "/html/taglib/portlet/runtime/error.jsp";
387    
388            private static final String _SETTINGS_SCOPE_DEFAULT =
389                    PortletPreferencesFactoryConstants.SETTINGS_SCOPE_PORTLET_INSTANCE;
390    
391            private static final Log _log = LogFactoryUtil.getLog(RuntimeTag.class);
392    
393            private String _defaultPreferences;
394            private String _instanceId;
395            private String _portletName;
396            private PortletProvider.Action _portletProviderAction;
397            private String _portletProviderClassName;
398            private String _queryString;
399            private String _settingsScope = _SETTINGS_SCOPE_DEFAULT;
400    
401    }