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