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