001    /**
002     * Copyright (c) 2000-2013 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.portal.action;
016    
017    import com.liferay.portal.kernel.audit.AuditMessage;
018    import com.liferay.portal.kernel.audit.AuditRouterUtil;
019    import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.portlet.PortletContainerUtil;
023    import com.liferay.portal.kernel.servlet.BrowserSnifferUtil;
024    import com.liferay.portal.kernel.servlet.MetaInfoCacheServletResponse;
025    import com.liferay.portal.kernel.servlet.PipingServletResponse;
026    import com.liferay.portal.kernel.util.HttpUtil;
027    import com.liferay.portal.kernel.util.JavaConstants;
028    import com.liferay.portal.kernel.util.ParamUtil;
029    import com.liferay.portal.kernel.util.PropsKeys;
030    import com.liferay.portal.kernel.util.ServerDetector;
031    import com.liferay.portal.kernel.util.StringPool;
032    import com.liferay.portal.kernel.util.Validator;
033    import com.liferay.portal.model.Layout;
034    import com.liferay.portal.model.LayoutConstants;
035    import com.liferay.portal.model.Portlet;
036    import com.liferay.portal.model.User;
037    import com.liferay.portal.security.permission.ActionKeys;
038    import com.liferay.portal.service.PortletLocalServiceUtil;
039    import com.liferay.portal.struts.ActionConstants;
040    import com.liferay.portal.struts.StrutsUtil;
041    import com.liferay.portal.theme.ThemeDisplay;
042    import com.liferay.portal.util.PortalUtil;
043    import com.liferay.portal.util.PrefsPropsUtil;
044    import com.liferay.portal.util.PropsUtil;
045    import com.liferay.portal.util.PropsValues;
046    import com.liferay.portal.util.WebKeys;
047    import com.liferay.portlet.PortletRequestImpl;
048    import com.liferay.portlet.RenderParametersPool;
049    import com.liferay.portlet.login.util.LoginUtil;
050    
051    import java.util.Arrays;
052    import java.util.HashSet;
053    import java.util.Set;
054    
055    import javax.portlet.PortletRequest;
056    import javax.portlet.PortletURL;
057    
058    import javax.servlet.RequestDispatcher;
059    import javax.servlet.ServletContext;
060    import javax.servlet.http.HttpServletRequest;
061    import javax.servlet.http.HttpServletResponse;
062    import javax.servlet.http.HttpSession;
063    
064    import org.apache.struts.action.Action;
065    import org.apache.struts.action.ActionForm;
066    import org.apache.struts.action.ActionForward;
067    import org.apache.struts.action.ActionMapping;
068    
069    /**
070     * @author Brian Wing Shun Chan
071     * @author Shuyang Zhou
072     */
073    public class LayoutAction extends Action {
074    
075            public static final String[] LAYOUT_RESET_PORTLET_IDS = PropsUtil.getArray(
076                    "layout.reset.portlet.ids");
077    
078            public LayoutAction() {
079                    _layoutResetPortletIds = new HashSet<String>(Arrays.asList(
080                            LAYOUT_RESET_PORTLET_IDS));
081    
082                    _layoutResetPortletIds.add(StringPool.BLANK);
083            }
084    
085            @Override
086            public ActionForward execute(
087                            ActionMapping actionMapping, ActionForm actionForm,
088                            HttpServletRequest request, HttpServletResponse response)
089                    throws Exception {
090    
091                    MetaInfoCacheServletResponse metaInfoCacheServletResponse =
092                            new MetaInfoCacheServletResponse(response);
093    
094                    try {
095                            return doExecute(
096                                    actionMapping, actionForm, request,
097                                    metaInfoCacheServletResponse);
098                    }
099                    finally {
100                            metaInfoCacheServletResponse.finishResponse(false);
101                    }
102            }
103    
104            protected ActionForward doExecute(
105                            ActionMapping actionMapping, ActionForm actionForm,
106                            HttpServletRequest request, HttpServletResponse response)
107                    throws Exception {
108    
109                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
110                            WebKeys.THEME_DISPLAY);
111    
112                    Boolean layoutDefault = (Boolean)request.getAttribute(
113                            WebKeys.LAYOUT_DEFAULT);
114    
115                    if (Boolean.TRUE.equals(layoutDefault)) {
116                            Layout requestedLayout = (Layout)request.getAttribute(
117                                    WebKeys.REQUESTED_LAYOUT);
118    
119                            if (requestedLayout != null) {
120                                    String redirectParam = "redirect";
121    
122                                    if (Validator.isNotNull(PropsValues.AUTH_LOGIN_PORTLET_NAME)) {
123                                            redirectParam =
124                                                    PortalUtil.getPortletNamespace(
125                                                            PropsValues.AUTH_LOGIN_PORTLET_NAME) +
126                                                    redirectParam;
127                                    }
128    
129                                    String authLoginURL = null;
130    
131                                    if (PrefsPropsUtil.getBoolean(
132                                                    themeDisplay.getCompanyId(), PropsKeys.CAS_AUTH_ENABLED,
133                                                    PropsValues.CAS_AUTH_ENABLED) ||
134                                            PrefsPropsUtil.getBoolean(
135                                                    themeDisplay.getCompanyId(),
136                                                    PropsKeys.OPEN_SSO_AUTH_ENABLED,
137                                                    PropsValues.OPEN_SSO_AUTH_ENABLED)) {
138    
139                                            authLoginURL = themeDisplay.getURLSignIn();
140                                    }
141    
142                                    if (Validator.isNull(authLoginURL)) {
143                                            authLoginURL = PortalUtil.getSiteLoginURL(themeDisplay);
144                                    }
145    
146                                    if (Validator.isNull(authLoginURL)) {
147                                            authLoginURL = PropsValues.AUTH_LOGIN_URL;
148                                    }
149    
150                                    if (Validator.isNull(authLoginURL)) {
151                                            PortletURL loginURL = LoginUtil.getLoginURL(
152                                                    request, themeDisplay.getPlid());
153    
154                                            authLoginURL = loginURL.toString();
155                                    }
156    
157                                    authLoginURL = HttpUtil.setParameter(
158                                            authLoginURL, "p_p_id",
159                                            PropsValues.AUTH_LOGIN_PORTLET_NAME);
160    
161                                    String currentURL = PortalUtil.getCurrentURL(request);
162    
163                                    authLoginURL = HttpUtil.setParameter(
164                                            authLoginURL, redirectParam, currentURL);
165    
166                                    if (_log.isDebugEnabled()) {
167                                            _log.debug("Redirect requested layout to " + authLoginURL);
168                                    }
169    
170                                    response.sendRedirect(authLoginURL);
171                            }
172                            else {
173                                    Layout layout = themeDisplay.getLayout();
174    
175                                    String redirect = PortalUtil.getLayoutURL(layout, themeDisplay);
176    
177                                    if (_log.isDebugEnabled()) {
178                                            _log.debug("Redirect default layout to " + redirect);
179                                    }
180    
181                                    response.sendRedirect(redirect);
182                            }
183    
184                            return null;
185                    }
186    
187                    long plid = ParamUtil.getLong(request, "p_l_id");
188    
189                    if (_log.isDebugEnabled()) {
190                            _log.debug("p_l_id is " + plid);
191                    }
192    
193                    if (plid > 0) {
194                            Layout layout = themeDisplay.getLayout();
195    
196                            if (layout != null) {
197                                    plid = layout.getPlid();
198                            }
199    
200                            ActionForward actionForward = processLayout(
201                                    actionMapping, request, response, plid);
202    
203                            return actionForward;
204                    }
205    
206                    try {
207                            forwardLayout(request);
208    
209                            return actionMapping.findForward(
210                                    ActionConstants.COMMON_FORWARD_JSP);
211                    }
212                    catch (Exception e) {
213                            PortalUtil.sendError(e, request, response);
214    
215                            return null;
216                    }
217            }
218    
219            protected void forwardLayout(HttpServletRequest request) throws Exception {
220                    Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
221    
222                    long plid = LayoutConstants.DEFAULT_PLID;
223    
224                    String layoutFriendlyURL = null;
225    
226                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
227                            WebKeys.THEME_DISPLAY);
228    
229                    if (layout != null) {
230                            plid = layout.getPlid();
231    
232                            layoutFriendlyURL = PortalUtil.getLayoutFriendlyURL(
233                                    layout, themeDisplay);
234                    }
235    
236                    String forwardURL = layoutFriendlyURL;
237    
238                    if (Validator.isNull(forwardURL)) {
239                            forwardURL =
240                                    themeDisplay.getPathMain() + "/portal/layout?p_l_id=" + plid;
241                    }
242    
243                    if (Validator.isNotNull(themeDisplay.getDoAsUserId())) {
244                            forwardURL = HttpUtil.addParameter(
245                                    forwardURL, "doAsUserId", themeDisplay.getDoAsUserId());
246                    }
247    
248                    if (Validator.isNotNull(themeDisplay.getDoAsUserLanguageId())) {
249                            forwardURL = HttpUtil.addParameter(
250                                    forwardURL, "doAsUserLanguageId",
251                                    themeDisplay.getDoAsUserLanguageId());
252                    }
253    
254                    if (_log.isDebugEnabled()) {
255                            _log.debug("Forward layout to " + forwardURL);
256                    }
257    
258                    request.setAttribute(WebKeys.FORWARD_URL, forwardURL);
259            }
260    
261            protected void includeLayoutContent(
262                            HttpServletRequest request, HttpServletResponse response,
263                            ThemeDisplay themeDisplay, Layout layout, String portletId)
264                    throws Exception {
265    
266                    ServletContext servletContext = (ServletContext)request.getAttribute(
267                            WebKeys.CTX);
268    
269                    String path = StrutsUtil.TEXT_HTML_DIR;
270    
271                    if (BrowserSnifferUtil.isWap(request)) {
272                            path = StrutsUtil.TEXT_WAP_DIR;
273                    }
274    
275                    // Manually check the p_p_id. See LEP-1724.
276    
277                    if (Validator.isNotNull(portletId)) {
278                            if (layout.isTypePanel()) {
279                                    path += "/portal/layout/view/panel.jsp";
280                            }
281                            else if (layout.isTypeControlPanel()) {
282                                    path += "/portal/layout/view/control_panel.jsp";
283                            }
284                            else {
285                                    path += "/portal/layout/view/portlet.jsp";
286                            }
287                    }
288                    else {
289                            path += PortalUtil.getLayoutViewPage(layout);
290                    }
291    
292                    RequestDispatcher requestDispatcher =
293                            servletContext.getRequestDispatcher(path);
294    
295                    UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
296    
297                    PipingServletResponse pipingServletResponse = new PipingServletResponse(
298                            response, unsyncStringWriter);
299    
300                    String contentType = pipingServletResponse.getContentType();
301    
302                    requestDispatcher.include(request, pipingServletResponse);
303    
304                    if (contentType != null) {
305                            response.setContentType(contentType);
306                    }
307    
308                    request.setAttribute(
309                            WebKeys.LAYOUT_CONTENT, unsyncStringWriter.getStringBundler());
310            }
311    
312            protected ActionForward processLayout(
313                            ActionMapping actionMapping, HttpServletRequest request,
314                            HttpServletResponse response, long plid)
315                    throws Exception {
316    
317                    HttpSession session = request.getSession();
318    
319                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
320                            WebKeys.THEME_DISPLAY);
321    
322                    try {
323                            Layout layout = themeDisplay.getLayout();
324    
325                            if ((layout != null) && layout.isTypeURL()) {
326                                    String redirect = PortalUtil.getLayoutActualURL(layout);
327    
328                                    response.sendRedirect(redirect);
329    
330                                    return null;
331                            }
332    
333                            Long previousLayoutPlid = (Long)session.getAttribute(
334                                    WebKeys.PREVIOUS_LAYOUT_PLID);
335    
336                            if ((previousLayoutPlid == null) ||
337                                    (layout.getPlid() != previousLayoutPlid.longValue())) {
338    
339                                    session.setAttribute(
340                                            WebKeys.PREVIOUS_LAYOUT_PLID, layout.getPlid());
341    
342                                    if (themeDisplay.isSignedIn() &&
343                                            PropsValues.
344                                                    AUDIT_MESSAGE_COM_LIFERAY_PORTAL_MODEL_LAYOUT_VIEW &&
345                                            AuditRouterUtil.isDeployed()) {
346    
347                                            User user = themeDisplay.getUser();
348    
349                                            AuditMessage auditMessage = new AuditMessage(
350                                                    ActionKeys.VIEW, user.getCompanyId(), user.getUserId(),
351                                                    user.getFullName(), Layout.class.getName(),
352                                                    String.valueOf(layout.getPlid()));
353    
354                                            AuditRouterUtil.route(auditMessage);
355                                    }
356                            }
357    
358                            boolean resetLayout = ParamUtil.getBoolean(
359                                    request, "p_l_reset", PropsValues.LAYOUT_DEFAULT_P_L_RESET);
360    
361                            String portletId = ParamUtil.getString(request, "p_p_id");
362    
363                            if (resetLayout && (_layoutResetPortletIds.contains(portletId) ||
364                                     ((previousLayoutPlid != null) &&
365                                      (layout.getPlid() != previousLayoutPlid.longValue())))) {
366    
367                                    // Always clear render parameters on a layout url, but do not
368                                    // clear on portlet urls invoked on the same layout
369    
370                                    RenderParametersPool.clear(request, plid);
371                            }
372    
373                            Portlet portlet = null;
374    
375                            if (Validator.isNotNull(portletId)) {
376                                    long companyId = PortalUtil.getCompanyId(request);
377    
378                                    portlet = PortletLocalServiceUtil.getPortletById(
379                                            companyId, portletId);
380                            }
381    
382                            if (portlet != null) {
383                                    PortletContainerUtil.preparePortlet(request, portlet);
384    
385                                    if (themeDisplay.isLifecycleAction()) {
386                                            PortletContainerUtil.processAction(
387                                                    request, response, portlet);
388    
389                                            if (response.isCommitted()) {
390                                                    return null;
391                                            }
392                                    }
393                                    else if (themeDisplay.isLifecycleResource()) {
394                                            PortletContainerUtil.serveResource(
395                                                    request, response, portlet);
396    
397                                            return null;
398                                    }
399                            }
400    
401                            if (layout != null) {
402                                    if (themeDisplay.isStateExclusive()) {
403                                            PortletContainerUtil.render(request, response, portlet);
404    
405                                            return null;
406                                    }
407                                    else {
408    
409                                            // Include layout content before the page loads because
410                                            // portlets on the page can set the page title and page
411                                            // subtitle
412    
413                                            includeLayoutContent(
414                                                    request, response, themeDisplay, layout, portletId);
415                                    }
416                            }
417    
418                            return actionMapping.findForward("portal.layout");
419                    }
420                    catch (Exception e) {
421                            PortalUtil.sendError(e, request, response);
422    
423                            return null;
424                    }
425                    finally {
426                            if (!ServerDetector.isResin()) {
427                                    PortletRequest portletRequest =
428                                            (PortletRequest)request.getAttribute(
429                                                    JavaConstants.JAVAX_PORTLET_REQUEST);
430    
431                                    if (portletRequest != null) {
432                                            PortletRequestImpl portletRequestImpl =
433                                                    PortletRequestImpl.getPortletRequestImpl(
434                                                            portletRequest);
435    
436                                            portletRequestImpl.cleanUp();
437                                    }
438                            }
439                    }
440            }
441    
442            private static Log _log = LogFactoryUtil.getLog(LayoutAction.class);
443    
444            private Set<String> _layoutResetPortletIds;
445    
446    }