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