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                            LayoutTypePortlet layoutTypePortlet =
216                                    themeDisplay.getLayoutTypePortlet();
217    
218                            if (!layoutTypePortlet.isPortletEmbedded(portlet.getPortletId())) {
219                                    PortletPreferencesFactoryUtil.getLayoutPortletSetup(
220                                            themeDisplay.getCompanyId(), themeDisplay.getScopeGroupId(),
221                                            PortletKeys.PREFS_OWNER_TYPE_LAYOUT,
222                                            PortletKeys.PREFS_PLID_SHARED,
223                                            portletInstance.getPortletInstanceKey(),
224                                            defaultPreferences);
225    
226                                    writeJSONObject = true;
227                            }
228    
229                            if (PortletPreferencesLocalServiceUtil.getPortletPreferencesCount(
230                                            PortletKeys.PREFS_OWNER_TYPE_LAYOUT, themeDisplay.getPlid(),
231                                            portletInstance.getPortletInstanceKey()) < 1) {
232    
233                                    PortletPreferencesFactoryUtil.getLayoutPortletSetup(
234                                            layout, portletInstance.getPortletInstanceKey(),
235                                            defaultPreferences);
236                                    PortletPreferencesFactoryUtil.getPortletSetup(
237                                            request, portletInstance.getPortletInstanceKey(),
238                                            defaultPreferences);
239    
240                                    PortletLayoutListener portletLayoutListener =
241                                            portlet.getPortletLayoutListenerInstance();
242    
243                                    if (portletLayoutListener != null) {
244                                            portletLayoutListener.onAddToLayout(
245                                                    portletInstance.getPortletInstanceKey(),
246                                                    themeDisplay.getPlid());
247                                    }
248    
249                                    writeJSONObject = true;
250                            }
251    
252                            if (writeJSONObject) {
253                                    jsonObject = JSONFactoryUtil.createJSONObject();
254    
255                                    PortletJSONUtil.populatePortletJSONObject(
256                                            request, StringPool.BLANK, portlet, jsonObject);
257                            }
258    
259                            if (jsonObject != null) {
260                                    PortletJSONUtil.writeHeaderPaths(response, jsonObject);
261                            }
262    
263                            PortletContainerUtil.render(request, response, portlet);
264    
265                            if (jsonObject != null) {
266                                    PortletJSONUtil.writeFooterPaths(response, jsonObject);
267                            }
268                    }
269                    finally {
270                            restrictPortletServletRequest.mergeSharedAttributes();
271                    }
272            }
273    
274            @Override
275            public int doEndTag() throws JspException {
276                    try {
277                            HttpServletRequest request =
278                                    (HttpServletRequest)pageContext.getRequest();
279    
280                            Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
281    
282                            if (layout == null) {
283                                    return EVAL_PAGE;
284                            }
285    
286                            HttpServletResponse response =
287                                    (HttpServletResponse)pageContext.getResponse();
288    
289                            if (Validator.isNotNull(_portletProviderClassName) &&
290                                    (_portletProviderAction != null)) {
291    
292                                    doTag(
293                                            _portletProviderClassName, _portletProviderAction,
294                                            _instanceId, _queryString, _defaultPreferences, pageContext,
295                                            request, response);
296                            }
297                            else {
298                                    doTag(
299                                            _portletName, _instanceId, _queryString, _settingsScope,
300                                            _defaultPreferences, pageContext, request, response);
301                            }
302    
303                            return EVAL_PAGE;
304                    }
305                    catch (Exception e) {
306                            _log.error(e, e);
307    
308                            throw new JspException(e);
309                    }
310            }
311    
312            public void setDefaultPreferences(String defaultPreferences) {
313                    _defaultPreferences = defaultPreferences;
314            }
315    
316            public void setInstanceId(String instanceId) {
317                    _instanceId = instanceId;
318            }
319    
320            public void setPortletName(String portletName) {
321                    _portletName = portletName;
322            }
323    
324            public void setPortletProviderAction(
325                    PortletProvider.Action portletProviderAction) {
326    
327                    _portletProviderAction = portletProviderAction;
328            }
329    
330            public void setPortletProviderClassName(String portletProviderClassName) {
331                    _portletProviderClassName = portletProviderClassName;
332            }
333    
334            public void setQueryString(String queryString) {
335                    _queryString = queryString;
336            }
337    
338            public void setSettingsScope(String settingsScope) {
339                    _settingsScope = settingsScope;
340            }
341    
342            /**
343             * @see com.liferay.portal.model.impl.LayoutTypePortletImpl#getStaticPortlets(
344             *      String)
345             */
346            protected static Portlet getPortlet(long companyId, String portletId)
347                    throws Exception {
348    
349                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
350                            companyId, portletId);
351    
352                    // See LayoutTypePortletImpl#getStaticPortlets for why we only clone
353                    // non-instanceable portlets
354    
355                    if (!portlet.isInstanceable()) {
356                            portlet = (Portlet)portlet.clone();
357                    }
358    
359                    portlet.setStatic(true);
360    
361                    return portlet;
362            }
363    
364            private static final String _ERROR_PAGE =
365                    "/html/taglib/portlet/runtime/error.jsp";
366    
367            private static final String _SETTINGS_SCOPE_DEFAULT =
368                    PortletPreferencesFactoryConstants.SETTINGS_SCOPE_PORTLET_INSTANCE;
369    
370            private static final Log _log = LogFactoryUtil.getLog(RuntimeTag.class);
371    
372            private String _defaultPreferences;
373            private String _instanceId;
374            private String _portletName;
375            private PortletProvider.Action _portletProviderAction;
376            private String _portletProviderClassName;
377            private String _queryString;
378            private String _settingsScope = _SETTINGS_SCOPE_DEFAULT;
379    
380    }