001    /**
002     * Copyright (c) 2000-2012 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.messaging.DestinationNames;
023    import com.liferay.portal.kernel.messaging.MessageBusUtil;
024    import com.liferay.portal.kernel.portlet.PortletContainerUtil;
025    import com.liferay.portal.kernel.servlet.BrowserSnifferUtil;
026    import com.liferay.portal.kernel.servlet.MetaInfoCacheServletResponse;
027    import com.liferay.portal.kernel.servlet.PipingServletResponse;
028    import com.liferay.portal.kernel.util.HttpUtil;
029    import com.liferay.portal.kernel.util.JavaConstants;
030    import com.liferay.portal.kernel.util.ParamUtil;
031    import com.liferay.portal.kernel.util.PropsKeys;
032    import com.liferay.portal.kernel.util.ServerDetector;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.model.Layout;
035    import com.liferay.portal.model.LayoutConstants;
036    import com.liferay.portal.model.Portlet;
037    import com.liferay.portal.model.User;
038    import com.liferay.portal.security.permission.ActionKeys;
039    import com.liferay.portal.service.PortletLocalServiceUtil;
040    import com.liferay.portal.struts.ActionConstants;
041    import com.liferay.portal.struts.StrutsUtil;
042    import com.liferay.portal.theme.ThemeDisplay;
043    import com.liferay.portal.util.PortalUtil;
044    import com.liferay.portal.util.PrefsPropsUtil;
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 javax.portlet.PortletRequest;
052    import javax.portlet.PortletURL;
053    
054    import javax.servlet.RequestDispatcher;
055    import javax.servlet.ServletContext;
056    import javax.servlet.http.HttpServletRequest;
057    import javax.servlet.http.HttpServletResponse;
058    import javax.servlet.http.HttpSession;
059    
060    import org.apache.struts.action.Action;
061    import org.apache.struts.action.ActionForm;
062    import org.apache.struts.action.ActionForward;
063    import org.apache.struts.action.ActionMapping;
064    
065    /**
066     * @author Brian Wing Shun Chan
067     * @author Shuyang Zhou
068     */
069    public class LayoutAction extends Action {
070    
071            @Override
072            public ActionForward execute(
073                            ActionMapping mapping, ActionForm form, HttpServletRequest request,
074                            HttpServletResponse response)
075                    throws Exception {
076    
077                    MetaInfoCacheServletResponse metaInfoCacheServletResponse =
078                            new MetaInfoCacheServletResponse(response);
079    
080                    try {
081                            return doExecute(
082                                    mapping, form, request, metaInfoCacheServletResponse);
083                    }
084                    finally {
085                            metaInfoCacheServletResponse.finishResponse();
086                    }
087            }
088    
089            protected ActionForward doExecute(
090                            ActionMapping mapping, ActionForm form, HttpServletRequest request,
091                            HttpServletResponse response)
092                    throws Exception {
093    
094                    Boolean layoutDefault = (Boolean)request.getAttribute(
095                            WebKeys.LAYOUT_DEFAULT);
096    
097                    if (Boolean.TRUE.equals(layoutDefault)) {
098                            ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
099                                    WebKeys.THEME_DISPLAY);
100    
101                            Layout requestedLayout = (Layout)request.getAttribute(
102                                    WebKeys.REQUESTED_LAYOUT);
103    
104                            if (requestedLayout != null) {
105                                    String redirectParam = "redirect";
106    
107                                    if (Validator.isNotNull(PropsValues.AUTH_LOGIN_PORTLET_NAME)) {
108                                            redirectParam =
109                                                    PortalUtil.getPortletNamespace(
110                                                            PropsValues.AUTH_LOGIN_PORTLET_NAME) +
111                                                    redirectParam;
112                                    }
113    
114                                    String authLoginURL = null;
115    
116                                    if (PrefsPropsUtil.getBoolean(
117                                                    themeDisplay.getCompanyId(), PropsKeys.CAS_AUTH_ENABLED,
118                                                    PropsValues.CAS_AUTH_ENABLED) ||
119                                            PrefsPropsUtil.getBoolean(
120                                                    themeDisplay.getCompanyId(),
121                                                    PropsKeys.OPEN_SSO_AUTH_ENABLED,
122                                                    PropsValues.OPEN_SSO_AUTH_ENABLED)) {
123    
124                                            authLoginURL = themeDisplay.getURLSignIn();
125                                    }
126    
127                                    if (Validator.isNull(authLoginURL)) {
128                                            authLoginURL = PortalUtil.getSiteLoginURL(themeDisplay);
129                                    }
130    
131                                    if (Validator.isNull(authLoginURL)) {
132                                            authLoginURL = PropsValues.AUTH_LOGIN_URL;
133                                    }
134    
135                                    if (Validator.isNull(authLoginURL)) {
136                                            PortletURL loginURL = LoginUtil.getLoginURL(
137                                                    request, themeDisplay.getPlid());
138    
139                                            authLoginURL = loginURL.toString();
140                                    }
141    
142                                    authLoginURL = HttpUtil.setParameter(
143                                            authLoginURL, "p_p_id",
144                                            PropsValues.AUTH_LOGIN_PORTLET_NAME);
145    
146                                    String currentURL = PortalUtil.getCurrentURL(request);
147    
148                                    authLoginURL = HttpUtil.setParameter(
149                                            authLoginURL, redirectParam, currentURL);
150    
151                                    if (_log.isDebugEnabled()) {
152                                            _log.debug("Redirect requested layout to " + authLoginURL);
153                                    }
154    
155                                    response.sendRedirect(authLoginURL);
156                            }
157                            else {
158                                    Layout layout = themeDisplay.getLayout();
159    
160                                    String redirect = PortalUtil.getLayoutURL(layout, themeDisplay);
161    
162                                    if (_log.isDebugEnabled()) {
163                                            _log.debug("Redirect default layout to " + redirect);
164                                    }
165    
166                                    response.sendRedirect(redirect);
167                            }
168    
169                            return null;
170                    }
171    
172                    long plid = ParamUtil.getLong(request, "p_l_id");
173    
174                    if (_log.isDebugEnabled()) {
175                            _log.debug("p_l_id is " + plid);
176                    }
177    
178                    if (plid > 0) {
179                            ActionForward actionForward = processLayout(
180                                    mapping, request, response, plid);
181    
182                            return actionForward;
183                    }
184    
185                    try {
186                            forwardLayout(request);
187    
188                            return mapping.findForward(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 mapping, 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                                            MessageBusUtil.hasMessageListener(DestinationNames.AUDIT)) {
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 mapping.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)portletRequest;
404    
405                                            portletRequestImpl.cleanUp();
406                                    }
407                            }
408                    }
409            }
410    
411            private static Log _log = LogFactoryUtil.getLog(LayoutAction.class);
412    
413    }