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