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.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
022    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
023    import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
024    import com.liferay.portal.kernel.language.LanguageUtil;
025    import com.liferay.portal.kernel.log.Log;
026    import com.liferay.portal.kernel.log.LogFactoryUtil;
027    import com.liferay.portal.kernel.messaging.DestinationNames;
028    import com.liferay.portal.kernel.messaging.MessageBusUtil;
029    import com.liferay.portal.kernel.portlet.LiferayPortletMode;
030    import com.liferay.portal.kernel.portlet.PortletModeFactory;
031    import com.liferay.portal.kernel.portlet.WindowStateFactory;
032    import com.liferay.portal.kernel.servlet.BrowserSnifferUtil;
033    import com.liferay.portal.kernel.servlet.HeaderCacheServletResponse;
034    import com.liferay.portal.kernel.servlet.HttpHeaders;
035    import com.liferay.portal.kernel.servlet.PipingServletResponse;
036    import com.liferay.portal.kernel.servlet.ServletResponseUtil;
037    import com.liferay.portal.kernel.servlet.StringServletResponse;
038    import com.liferay.portal.kernel.upload.UploadServletRequest;
039    import com.liferay.portal.kernel.util.ArrayUtil;
040    import com.liferay.portal.kernel.util.Base64;
041    import com.liferay.portal.kernel.util.ContentTypes;
042    import com.liferay.portal.kernel.util.HttpUtil;
043    import com.liferay.portal.kernel.util.JavaConstants;
044    import com.liferay.portal.kernel.util.MapUtil;
045    import com.liferay.portal.kernel.util.ParamUtil;
046    import com.liferay.portal.kernel.util.PropsKeys;
047    import com.liferay.portal.kernel.util.ServerDetector;
048    import com.liferay.portal.kernel.util.StringPool;
049    import com.liferay.portal.kernel.util.Validator;
050    import com.liferay.portal.kernel.webdav.WebDAVStorage;
051    import com.liferay.portal.kernel.xml.QName;
052    import com.liferay.portal.model.Layout;
053    import com.liferay.portal.model.LayoutConstants;
054    import com.liferay.portal.model.LayoutTypePortlet;
055    import com.liferay.portal.model.Portlet;
056    import com.liferay.portal.model.PortletPreferencesIds;
057    import com.liferay.portal.model.PublicRenderParameter;
058    import com.liferay.portal.model.User;
059    import com.liferay.portal.security.auth.AuthTokenUtil;
060    import com.liferay.portal.security.permission.ActionKeys;
061    import com.liferay.portal.security.permission.PermissionChecker;
062    import com.liferay.portal.security.permission.PermissionThreadLocal;
063    import com.liferay.portal.service.LayoutLocalServiceUtil;
064    import com.liferay.portal.service.PortletLocalServiceUtil;
065    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
066    import com.liferay.portal.service.ServiceContext;
067    import com.liferay.portal.service.ServiceContextFactory;
068    import com.liferay.portal.service.ServiceContextThreadLocal;
069    import com.liferay.portal.service.permission.PortletPermissionUtil;
070    import com.liferay.portal.struts.ActionConstants;
071    import com.liferay.portal.struts.StrutsUtil;
072    import com.liferay.portal.theme.PortletDisplay;
073    import com.liferay.portal.theme.ThemeDisplay;
074    import com.liferay.portal.upload.UploadServletRequestImpl;
075    import com.liferay.portal.util.PortalUtil;
076    import com.liferay.portal.util.PrefsPropsUtil;
077    import com.liferay.portal.util.PropsValues;
078    import com.liferay.portal.util.WebKeys;
079    import com.liferay.portlet.ActionRequestFactory;
080    import com.liferay.portlet.ActionRequestImpl;
081    import com.liferay.portlet.ActionResponseFactory;
082    import com.liferay.portlet.ActionResponseImpl;
083    import com.liferay.portlet.EventImpl;
084    import com.liferay.portlet.EventRequestFactory;
085    import com.liferay.portlet.EventRequestImpl;
086    import com.liferay.portlet.EventResponseFactory;
087    import com.liferay.portlet.EventResponseImpl;
088    import com.liferay.portlet.InvokerPortlet;
089    import com.liferay.portlet.InvokerPortletImpl;
090    import com.liferay.portlet.PortletConfigFactoryUtil;
091    import com.liferay.portlet.PortletConfigImpl;
092    import com.liferay.portlet.PortletInstanceFactoryUtil;
093    import com.liferay.portlet.PortletPreferencesFactoryUtil;
094    import com.liferay.portlet.PortletQName;
095    import com.liferay.portlet.PortletQNameUtil;
096    import com.liferay.portlet.PortletRequestImpl;
097    import com.liferay.portlet.PortletURLImpl;
098    import com.liferay.portlet.PublicRenderParametersPool;
099    import com.liferay.portlet.RenderParametersPool;
100    import com.liferay.portlet.RenderRequestImpl;
101    import com.liferay.portlet.RenderResponseImpl;
102    import com.liferay.portlet.ResourceRequestFactory;
103    import com.liferay.portlet.ResourceRequestImpl;
104    import com.liferay.portlet.ResourceResponseFactory;
105    import com.liferay.portlet.ResourceResponseImpl;
106    import com.liferay.portlet.StateAwareResponseImpl;
107    import com.liferay.portlet.login.util.LoginUtil;
108    import com.liferay.util.servlet.filters.CacheResponseUtil;
109    
110    import java.io.InputStream;
111    import java.io.Serializable;
112    
113    import java.util.ArrayList;
114    import java.util.Enumeration;
115    import java.util.HashMap;
116    import java.util.List;
117    import java.util.Map;
118    
119    import javax.portlet.Event;
120    import javax.portlet.PortletConfig;
121    import javax.portlet.PortletContext;
122    import javax.portlet.PortletMode;
123    import javax.portlet.PortletPreferences;
124    import javax.portlet.PortletRequest;
125    import javax.portlet.PortletURL;
126    import javax.portlet.UnavailableException;
127    import javax.portlet.WindowState;
128    
129    import javax.servlet.RequestDispatcher;
130    import javax.servlet.ServletContext;
131    import javax.servlet.http.HttpServletRequest;
132    import javax.servlet.http.HttpServletResponse;
133    import javax.servlet.http.HttpSession;
134    
135    import org.apache.struts.action.Action;
136    import org.apache.struts.action.ActionForm;
137    import org.apache.struts.action.ActionForward;
138    import org.apache.struts.action.ActionMapping;
139    
140    /**
141     * @author Brian Wing Shun Chan
142     */
143    public class LayoutAction extends Action {
144    
145            @Override
146            public ActionForward execute(
147                            ActionMapping mapping, ActionForm form, HttpServletRequest request,
148                            HttpServletResponse response)
149                    throws Exception {
150    
151                    HeaderCacheServletResponse headerCacheServletResponse = null;
152    
153                    if (response instanceof HeaderCacheServletResponse) {
154                            headerCacheServletResponse = (HeaderCacheServletResponse)response;
155                    }
156                    else {
157                            headerCacheServletResponse = new HeaderCacheServletResponse(
158                                    response);
159                    }
160    
161                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
162                            WebKeys.THEME_DISPLAY);
163    
164                    Layout layout = themeDisplay.getLayout();
165    
166                    Boolean layoutDefault = (Boolean)request.getAttribute(
167                            WebKeys.LAYOUT_DEFAULT);
168    
169                    if ((layoutDefault != null) && (layoutDefault.booleanValue())) {
170                            Layout requestedLayout = (Layout)request.getAttribute(
171                                    WebKeys.REQUESTED_LAYOUT);
172    
173                            if (requestedLayout != null) {
174                                    String redirectParam = "redirect";
175    
176                                    if (Validator.isNotNull(PropsValues.AUTH_LOGIN_PORTLET_NAME)) {
177                                            redirectParam =
178                                                    PortalUtil.getPortletNamespace(
179                                                            PropsValues.AUTH_LOGIN_PORTLET_NAME) +
180                                                    redirectParam;
181                                    }
182    
183                                    String authLoginURL = null;
184    
185                                    if (PrefsPropsUtil.getBoolean(
186                                                    themeDisplay.getCompanyId(), PropsKeys.CAS_AUTH_ENABLED,
187                                                    PropsValues.CAS_AUTH_ENABLED) ||
188                                            PrefsPropsUtil.getBoolean(
189                                                    themeDisplay.getCompanyId(),
190                                                    PropsKeys.OPEN_SSO_AUTH_ENABLED,
191                                                    PropsValues.OPEN_SSO_AUTH_ENABLED)) {
192    
193                                            authLoginURL = themeDisplay.getURLSignIn();
194                                    }
195    
196                                    if (Validator.isNull(authLoginURL)) {
197                                            authLoginURL = PortalUtil.getSiteLoginURL(themeDisplay);
198                                    }
199    
200                                    if (Validator.isNull(authLoginURL)) {
201                                            authLoginURL = PropsValues.AUTH_LOGIN_URL;
202                                    }
203    
204                                    if (Validator.isNull(authLoginURL)) {
205                                            PortletURL loginURL = LoginUtil.getLoginURL(
206                                                    request, themeDisplay.getPlid());
207    
208                                            authLoginURL = loginURL.toString();
209                                    }
210    
211                                    authLoginURL = HttpUtil.setParameter(
212                                            authLoginURL, "p_p_id",
213                                            PropsValues.AUTH_LOGIN_PORTLET_NAME);
214    
215                                    String currentURL = PortalUtil.getCurrentURL(request);
216    
217                                    authLoginURL = HttpUtil.setParameter(
218                                            authLoginURL, redirectParam, currentURL);
219    
220                                    if (_log.isDebugEnabled()) {
221                                            _log.debug("Redirect requested layout to " + authLoginURL);
222                                    }
223    
224                                    headerCacheServletResponse.sendRedirect(authLoginURL);
225                            }
226                            else {
227                                    String redirect = PortalUtil.getLayoutURL(layout, themeDisplay);
228    
229                                    if (_log.isDebugEnabled()) {
230                                            _log.debug("Redirect default layout to " + redirect);
231                                    }
232    
233                                    headerCacheServletResponse.sendRedirect(redirect);
234                            }
235    
236                            return null;
237                    }
238    
239                    long plid = ParamUtil.getLong(request, "p_l_id");
240    
241                    if (_log.isDebugEnabled()) {
242                            _log.debug("p_l_id is " + plid);
243                    }
244    
245                    if (plid > 0) {
246                            ActionForward actionForward = processLayout(
247                                    mapping, request, headerCacheServletResponse, plid);
248    
249                            String contentType = response.getContentType();
250    
251                            CacheResponseUtil.setHeaders(
252                                    response, headerCacheServletResponse.getHeaders());
253    
254                            if (contentType != null) {
255                                    response.setContentType(contentType);
256                            }
257    
258                            return actionForward;
259                    }
260                    else {
261                            try {
262                                    forwardLayout(request);
263    
264                                    return mapping.findForward(ActionConstants.COMMON_FORWARD_JSP);
265                            }
266                            catch (Exception e) {
267                                    PortalUtil.sendError(e, request, headerCacheServletResponse);
268    
269                                    CacheResponseUtil.setHeaders(
270                                            response, headerCacheServletResponse.getHeaders());
271    
272                                    return null;
273                            }
274                    }
275            }
276    
277            protected void forwardLayout(HttpServletRequest request) throws Exception {
278                    Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
279    
280                    long plid = LayoutConstants.DEFAULT_PLID;
281    
282                    String layoutFriendlyURL = null;
283    
284                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
285                            WebKeys.THEME_DISPLAY);
286    
287                    if (layout != null) {
288                            plid = layout.getPlid();
289    
290                            layoutFriendlyURL = PortalUtil.getLayoutFriendlyURL(
291                                    layout, themeDisplay);
292                    }
293    
294                    String forwardURL = layoutFriendlyURL;
295    
296                    if (Validator.isNull(forwardURL)) {
297                            forwardURL =
298                                    themeDisplay.getPathMain() + "/portal/layout?p_l_id=" + plid;
299                    }
300    
301                    if (Validator.isNotNull(themeDisplay.getDoAsUserId())) {
302                            forwardURL = HttpUtil.addParameter(
303                                    forwardURL, "doAsUserId", themeDisplay.getDoAsUserId());
304                    }
305    
306                    if (Validator.isNotNull(themeDisplay.getDoAsUserLanguageId())) {
307                            forwardURL = HttpUtil.addParameter(
308                                    forwardURL, "doAsUserLanguageId",
309                                    themeDisplay.getDoAsUserLanguageId());
310                    }
311    
312                    if (_log.isDebugEnabled()) {
313                            _log.debug("Forward layout to " + forwardURL);
314                    }
315    
316                    request.setAttribute(WebKeys.FORWARD_URL, forwardURL);
317            }
318    
319            protected List<LayoutTypePortlet> getLayoutTypePortlets(
320                            long groupId, boolean privateLayout)
321                    throws Exception {
322    
323                    List<LayoutTypePortlet> layoutTypePortlets =
324                            new ArrayList<LayoutTypePortlet>();
325    
326                    List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
327                            groupId, privateLayout, LayoutConstants.TYPE_PORTLET);
328    
329                    for (Layout layout : layouts) {
330                            if (!layout.isTypePortlet()) {
331                                    continue;
332                            }
333    
334                            LayoutTypePortlet layoutTypePortlet =
335                                    (LayoutTypePortlet)layout.getLayoutType();
336    
337                            layoutTypePortlets.add(layoutTypePortlet);
338                    }
339    
340                    return layoutTypePortlets;
341            }
342    
343            protected long getScopeGroupId(
344                            HttpServletRequest request, LayoutTypePortlet layoutTypePortlet,
345                            String portletId)
346                    throws PortalException, SystemException {
347    
348                    long scopeGroupId = 0;
349    
350                    Layout layoutTypePortletLayout = layoutTypePortlet.getLayout();
351    
352                    Layout requestLayout = (Layout)request.getAttribute(WebKeys.LAYOUT);
353    
354                    try {
355                            request.setAttribute(WebKeys.LAYOUT, layoutTypePortletLayout);
356    
357                            scopeGroupId = PortalUtil.getScopeGroupId(request, portletId);
358                    }
359                    finally {
360                            request.setAttribute(WebKeys.LAYOUT, requestLayout);
361                    }
362    
363                    if (scopeGroupId <= 0) {
364                            scopeGroupId = PortalUtil.getScopeGroupId(
365                                    layoutTypePortletLayout, portletId);
366                    }
367    
368                    return scopeGroupId;
369            }
370    
371            protected void includeLayoutContent(
372                            HttpServletRequest request, HttpServletResponse response,
373                            ThemeDisplay themeDisplay, Layout layout)
374                    throws Exception {
375    
376                    ServletContext servletContext = (ServletContext)request.getAttribute(
377                            WebKeys.CTX);
378    
379                    String path = StrutsUtil.TEXT_HTML_DIR;
380    
381                    if (BrowserSnifferUtil.isWap(request)) {
382                            path = StrutsUtil.TEXT_WAP_DIR;
383                    }
384    
385                    // Manually check the p_p_id. See LEP-1724.
386    
387                    if (themeDisplay.isStateExclusive() ||
388                            Validator.isNotNull(ParamUtil.getString(request, "p_p_id"))) {
389    
390                            if (layout.isTypePanel()) {
391                                    path += "/portal/layout/view/panel.jsp";
392                            }
393                            else if (layout.isTypeControlPanel()) {
394                                    path += "/portal/layout/view/control_panel.jsp";
395                            }
396                            else {
397                                    path += "/portal/layout/view/portlet.jsp";
398                            }
399                    }
400                    else {
401                            path += PortalUtil.getLayoutViewPage(layout);
402                    }
403    
404                    RequestDispatcher requestDispatcher =
405                            servletContext.getRequestDispatcher(path);
406    
407                    UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
408    
409                    PipingServletResponse pipingServletResponse = new PipingServletResponse(
410                            response, unsyncStringWriter);
411    
412                    String contentType = pipingServletResponse.getContentType();
413    
414                    requestDispatcher.include(request, pipingServletResponse);
415    
416                    if (contentType != null) {
417                            pipingServletResponse.setContentType(contentType);
418                    }
419    
420                    request.setAttribute(
421                            WebKeys.LAYOUT_CONTENT, unsyncStringWriter.getStringBundler());
422            }
423    
424            protected void processEvent(
425                            PortletRequestImpl portletRequestImpl,
426                            StateAwareResponseImpl stateAwareResponseImpl,
427                            List<LayoutTypePortlet> layoutTypePortlets,
428                            LayoutTypePortlet layoutTypePortlet, Portlet portlet, Event event)
429                    throws Exception {
430    
431                    HttpServletRequest request = portletRequestImpl.getHttpServletRequest();
432                    HttpServletResponse response =
433                            stateAwareResponseImpl.getHttpServletResponse();
434                    HttpSession session = request.getSession();
435    
436                    String portletId = portlet.getPortletId();
437    
438                    ServletContext servletContext =
439                            (ServletContext)request.getAttribute(WebKeys.CTX);
440    
441                    InvokerPortlet invokerPortlet = PortletInstanceFactoryUtil.create(
442                            portlet, servletContext);
443    
444                    PortletConfig portletConfig = PortletConfigFactoryUtil.create(
445                            portlet, servletContext);
446                    PortletContext portletContext = portletConfig.getPortletContext();
447    
448                    WindowState windowState = null;
449    
450                    if (layoutTypePortlet.hasStateMaxPortletId(portletId)) {
451                            windowState = WindowState.MAXIMIZED;
452                    }
453                    else if (layoutTypePortlet.hasStateMinPortletId(portletId)) {
454                            windowState = WindowState.MINIMIZED;
455                    }
456                    else {
457                            windowState = WindowState.NORMAL;
458                    }
459    
460                    PortletMode portletMode = null;
461    
462                    if (layoutTypePortlet.hasModeAboutPortletId(portletId)) {
463                            portletMode = LiferayPortletMode.ABOUT;
464                    }
465                    else if (layoutTypePortlet.hasModeConfigPortletId(portletId)) {
466                            portletMode = LiferayPortletMode.CONFIG;
467                    }
468                    else if (layoutTypePortlet.hasModeEditPortletId(portletId)) {
469                            portletMode = PortletMode.EDIT;
470                    }
471                    else if (layoutTypePortlet.hasModeEditDefaultsPortletId(portletId)) {
472                            portletMode = LiferayPortletMode.EDIT_DEFAULTS;
473                    }
474                    else if (layoutTypePortlet.hasModeEditGuestPortletId(portletId)) {
475                            portletMode = LiferayPortletMode.EDIT_GUEST;
476                    }
477                    else if (layoutTypePortlet.hasModeHelpPortletId(portletId)) {
478                            portletMode = PortletMode.HELP;
479                    }
480                    else if (layoutTypePortlet.hasModePreviewPortletId(portletId)) {
481                            portletMode = LiferayPortletMode.PREVIEW;
482                    }
483                    else if (layoutTypePortlet.hasModePrintPortletId(portletId)) {
484                            portletMode = LiferayPortletMode.PRINT;
485                    }
486                    else {
487                            portletMode = PortletMode.VIEW;
488                    }
489    
490                    long scopeGroupId = getScopeGroupId(
491                            request, layoutTypePortlet, portletId);
492    
493                    Layout layoutTypePortletLayout = layoutTypePortlet.getLayout();
494    
495                    PortletPreferences portletPreferences =
496                            PortletPreferencesFactoryUtil.getPortletSetup(
497                                    scopeGroupId, layoutTypePortletLayout, portletId, null);
498    
499                    EventRequestImpl eventRequestImpl = EventRequestFactory.create(
500                            request, portlet, invokerPortlet, portletContext, windowState,
501                            portletMode, portletPreferences, layoutTypePortletLayout.getPlid());
502    
503                    eventRequestImpl.setEvent(
504                            serializeEvent(event, invokerPortlet.getPortletClassLoader()));
505    
506                    Layout layout = stateAwareResponseImpl.getLayout();
507    
508                    EventResponseImpl eventResponseImpl = EventResponseFactory.create(
509                            eventRequestImpl, response, portletId,
510                            stateAwareResponseImpl.getUser(), layout);
511    
512                    eventRequestImpl.defineObjects(portletConfig, eventResponseImpl);
513    
514                    try {
515                            try {
516                                    InvokerPortletImpl.clearResponse(
517                                            session, layout.getPrimaryKey(), portletId,
518                                            LanguageUtil.getLanguageId(eventRequestImpl));
519    
520                                    invokerPortlet.processEvent(
521                                            eventRequestImpl, eventResponseImpl);
522    
523                                    if (eventResponseImpl.isCalledSetRenderParameter()) {
524                                            Map<String, String[]> renderParameterMap =
525                                                    new HashMap<String, String[]>();
526    
527                                            MapUtil.copy(
528                                                    eventResponseImpl.getRenderParameterMap(),
529                                                    renderParameterMap);
530    
531                                            RenderParametersPool.put(
532                                                    request, layout.getPlid(), portletId,
533                                                    renderParameterMap);
534                                    }
535                            }
536                            catch (UnavailableException ue) {
537                                    throw ue;
538                            }
539    
540                            processEvents(
541                                    eventRequestImpl, eventResponseImpl, layoutTypePortlets);
542                    }
543                    finally {
544                            eventRequestImpl.cleanUp();
545                    }
546            }
547    
548            protected void processEvents(
549                            PortletRequestImpl portletRequestImpl,
550                            StateAwareResponseImpl stateAwareResponseImpl,
551                            List<LayoutTypePortlet> layoutTypePortlets)
552                    throws Exception {
553    
554                    List<Event> events = stateAwareResponseImpl.getEvents();
555    
556                    if (events.size() == 0) {
557                            return;
558                    }
559    
560                    for (Event event : events) {
561                            javax.xml.namespace.QName qName = event.getQName();
562    
563                            for (LayoutTypePortlet layoutTypePortlet : layoutTypePortlets) {
564                                    List<Portlet> portlets = layoutTypePortlet.getAllPortlets();
565    
566                                    for (Portlet portlet : portlets) {
567                                            QName processingQName = portlet.getProcessingEvent(
568                                                    qName.getNamespaceURI(), qName.getLocalPart());
569    
570                                            if (processingQName != null) {
571                                                    processEvent(
572                                                            portletRequestImpl, stateAwareResponseImpl,
573                                                            layoutTypePortlets, layoutTypePortlet, portlet,
574                                                            event);
575                                            }
576                                    }
577                            }
578                    }
579            }
580    
581            protected ActionForward processLayout(
582                            ActionMapping mapping, HttpServletRequest request,
583                            HttpServletResponse response, long plid)
584                    throws Exception {
585    
586                    HttpSession session = request.getSession();
587    
588                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
589                            WebKeys.THEME_DISPLAY);
590    
591                    try {
592                            Layout layout = themeDisplay.getLayout();
593    
594                            boolean resetLayout = ParamUtil.getBoolean(
595                                    request, "p_l_reset", PropsValues.LAYOUT_DEFAULT_P_L_RESET);
596    
597                            String portletId = ParamUtil.getString(request, "p_p_id");
598    
599                            Layout previousLayout = (Layout)session.getAttribute(
600                                    WebKeys.PREVIOUS_LAYOUT);
601    
602                            if ((previousLayout == null) ||
603                                    (layout.getPlid() != previousLayout.getPlid())) {
604    
605                                    session.setAttribute(WebKeys.PREVIOUS_LAYOUT, layout);
606    
607                                    if (themeDisplay.isSignedIn() &&
608                                            PropsValues.
609                                                    AUDIT_MESSAGE_COM_LIFERAY_PORTAL_MODEL_LAYOUT_VIEW &&
610                                            MessageBusUtil.hasMessageListener(DestinationNames.AUDIT)) {
611    
612                                            User user = themeDisplay.getUser();
613    
614                                            AuditMessage auditMessage = new AuditMessage(
615                                                    ActionKeys.VIEW, user.getCompanyId(), user.getUserId(),
616                                                    user.getFullName(), Layout.class.getName(),
617                                                    String.valueOf(layout.getPlid()));
618    
619                                            AuditRouterUtil.route(auditMessage);
620                                    }
621                            }
622    
623                            if (!PropsValues.TCK_URL && resetLayout &&
624                                    (Validator.isNull(portletId) ||
625                                     ((previousLayout != null) &&
626                                      (layout.getPlid() != previousLayout.getPlid())))) {
627    
628                                    // Always clear render parameters on a layout url, but do not
629                                    // clear on portlet urls invoked on the same layout
630    
631                                    RenderParametersPool.clear(request, plid);
632                            }
633    
634                            if (themeDisplay.isLifecycleAction()) {
635                                    Portlet portlet = processPortletRequest(
636                                            request, response, PortletRequest.ACTION_PHASE);
637    
638                                    if (portlet != null) {
639                                            ActionResponseImpl actionResponseImpl =
640                                                    (ActionResponseImpl)request.getAttribute(
641                                                            JavaConstants.JAVAX_PORTLET_RESPONSE);
642    
643                                            String redirectLocation =
644                                                    actionResponseImpl.getRedirectLocation();
645    
646                                            if (Validator.isNotNull(redirectLocation)) {
647                                                    response.sendRedirect(redirectLocation);
648    
649                                                    return null;
650                                            }
651    
652                                            if (portlet.isActionURLRedirect()) {
653                                                    redirectActionURL(
654                                                            request, response, actionResponseImpl, portlet);
655    
656                                                    return null;
657                                            }
658                                    }
659                            }
660                            else if (themeDisplay.isLifecycleRender()) {
661                                    processPortletRequest(
662                                            request, response, PortletRequest.RENDER_PHASE);
663                            }
664    
665                            if (themeDisplay.isLifecycleResource()) {
666                                    processPortletRequest(
667                                            request, response, PortletRequest.RESOURCE_PHASE);
668    
669                                    return null;
670                            }
671                            else {
672                                    if (response.isCommitted()) {
673                                            return null;
674                                    }
675    
676                                    if (layout != null) {
677    
678                                            // Include layout content before the page loads because
679                                            // portlets on the page can set the page title and page
680                                            // subtitle
681    
682                                            includeLayoutContent(
683                                                    request, response, themeDisplay, layout);
684    
685                                            if (themeDisplay.isStateExclusive()) {
686                                                    renderExclusive(request, response, themeDisplay);
687    
688                                                    return null;
689                                            }
690                                    }
691    
692                                    return mapping.findForward("portal.layout");
693                            }
694                    }
695                    catch (Exception e) {
696                            PortalUtil.sendError(e, request, response);
697    
698                            return null;
699                    }
700                    finally {
701                            if (!ServerDetector.isResin()) {
702                                    PortletRequest portletRequest =
703                                            (PortletRequest)request.getAttribute(
704                                                    JavaConstants.JAVAX_PORTLET_REQUEST);
705    
706                                    if (portletRequest != null) {
707                                            PortletRequestImpl portletRequestImpl =
708                                                    (PortletRequestImpl)portletRequest;
709    
710                                            portletRequestImpl.cleanUp();
711                                    }
712                            }
713                    }
714            }
715    
716            protected Portlet processPortletRequest(
717                            HttpServletRequest request, HttpServletResponse response,
718                            String lifecycle)
719                    throws Exception {
720    
721                    HttpSession session = request.getSession();
722    
723                    long companyId = PortalUtil.getCompanyId(request);
724                    User user = PortalUtil.getUser(request);
725                    Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
726    
727                    String portletId = ParamUtil.getString(request, "p_p_id");
728    
729                    if (Validator.isNull(portletId)) {
730                            return null;
731                    }
732    
733                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
734                            companyId, portletId);
735    
736                    if (portlet == null) {
737                            return null;
738                    }
739    
740                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
741                            WebKeys.THEME_DISPLAY);
742    
743                    long scopeGroupId = PortalUtil.getScopeGroupId(request, portletId);
744    
745                    themeDisplay.setScopeGroupId(scopeGroupId);
746    
747                    ServletContext servletContext = (ServletContext)request.getAttribute(
748                            WebKeys.CTX);
749    
750                    InvokerPortlet invokerPortlet = PortletInstanceFactoryUtil.create(
751                            portlet, servletContext);
752    
753                    if (user != null) {
754                            InvokerPortletImpl.clearResponse(
755                                    session, layout.getPrimaryKey(), portletId,
756                                    LanguageUtil.getLanguageId(request));
757                    }
758    
759                    PortletConfig portletConfig = PortletConfigFactoryUtil.create(
760                            portlet, servletContext);
761                    PortletContext portletContext = portletConfig.getPortletContext();
762    
763                    WindowState windowState = WindowStateFactory.getWindowState(
764                            ParamUtil.getString(request, "p_p_state"));
765    
766                    if (layout.isTypeControlPanel() &&
767                            ((windowState == null) || windowState.equals(WindowState.NORMAL) ||
768                             (Validator.isNull(windowState.toString())))) {
769    
770                            windowState = WindowState.MAXIMIZED;
771                    }
772    
773                    PortletMode portletMode = PortletModeFactory.getPortletMode(
774                            ParamUtil.getString(request, "p_p_mode"));
775    
776                    PortletPreferencesIds portletPreferencesIds =
777                            PortletPreferencesFactoryUtil.getPortletPreferencesIds(
778                                    request, portletId);
779    
780                    PortletPreferences portletPreferences = null;
781    
782                    if (PortalUtil.isAllowAddPortletDefaultResource(request, portlet)) {
783                            portletPreferences =
784                                    PortletPreferencesLocalServiceUtil.getPreferences(
785                                            portletPreferencesIds);
786                    }
787                    else {
788                            portletPreferences =
789                                    PortletPreferencesLocalServiceUtil.getStrictPreferences(
790                                            portletPreferencesIds);
791                    }
792    
793                    processPublicRenderParameters(request, layout, portlet);
794    
795                    PermissionChecker permissionChecker =
796                            PermissionThreadLocal.getPermissionChecker();
797    
798                    if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
799                            String contentType = request.getHeader(HttpHeaders.CONTENT_TYPE);
800    
801                            if (_log.isDebugEnabled()) {
802                                    _log.debug("Content type " + contentType);
803                            }
804    
805                            UploadServletRequest uploadServletRequest = null;
806    
807                            try {
808                                    if ((contentType != null) &&
809                                            (contentType.startsWith(
810                                                    ContentTypes.MULTIPART_FORM_DATA))) {
811    
812                                            PortletConfigImpl invokerPortletConfigImpl =
813                                                    (PortletConfigImpl)invokerPortlet.getPortletConfig();
814    
815                                            if (invokerPortlet.isStrutsPortlet() ||
816                                                    ((invokerPortletConfigImpl != null) &&
817                                                     (!invokerPortletConfigImpl.isWARFile()))) {
818    
819                                                    uploadServletRequest = new UploadServletRequestImpl(
820                                                            request);
821    
822                                                    request = uploadServletRequest;
823                                            }
824                                    }
825    
826                                    if (PropsValues.AUTH_TOKEN_CHECK_ENABLED &&
827                                            invokerPortlet.isCheckAuthToken()) {
828    
829                                            AuthTokenUtil.check(request);
830                                    }
831    
832                                    ActionRequestImpl actionRequestImpl =
833                                            ActionRequestFactory.create(
834                                                    request, portlet, invokerPortlet, portletContext,
835                                                    windowState, portletMode, portletPreferences,
836                                                    layout.getPlid());
837    
838                                    ActionResponseImpl actionResponseImpl =
839                                            ActionResponseFactory.create(
840                                                    actionRequestImpl, response, portletId, user, layout,
841                                                    windowState, portletMode);
842    
843                                    actionRequestImpl.defineObjects(
844                                            portletConfig, actionResponseImpl);
845    
846                                    ServiceContext serviceContext =
847                                            ServiceContextFactory.getInstance(actionRequestImpl);
848    
849                                    ServiceContextThreadLocal.pushServiceContext(serviceContext);
850    
851                                    boolean access = PortletPermissionUtil.hasAccessPermission(
852                                            permissionChecker, scopeGroupId, layout, portlet,
853                                            portletMode);
854    
855                                    if (access) {
856                                            invokerPortlet.processAction(
857                                                    actionRequestImpl, actionResponseImpl);
858    
859                                            actionResponseImpl.transferHeaders(response);
860                                    }
861    
862                                    RenderParametersPool.put(
863                                            request, layout.getPlid(), portletId,
864                                            actionResponseImpl.getRenderParameterMap());
865    
866                                    List<LayoutTypePortlet> layoutTypePortlets = null;
867    
868                                    if (!actionResponseImpl.getEvents().isEmpty()) {
869                                            if (PropsValues.PORTLET_EVENT_DISTRIBUTION_LAYOUT_SET) {
870                                                    layoutTypePortlets = getLayoutTypePortlets(
871                                                            layout.getGroupId(), layout.isPrivateLayout());
872                                            }
873                                            else {
874                                                    if (layout.isTypePortlet()) {
875                                                            LayoutTypePortlet layoutTypePortlet =
876                                                                    (LayoutTypePortlet)layout.getLayoutType();
877    
878                                                            layoutTypePortlets =
879                                                                    new ArrayList<LayoutTypePortlet>();
880    
881                                                            layoutTypePortlets.add(layoutTypePortlet);
882                                                    }
883                                            }
884    
885                                            processEvents(
886                                                    actionRequestImpl, actionResponseImpl,
887                                                    layoutTypePortlets);
888    
889                                            actionRequestImpl.defineObjects(
890                                                    portletConfig, actionResponseImpl);
891                                    }
892                            }
893                            finally {
894                                    if (uploadServletRequest != null) {
895                                            uploadServletRequest.cleanUp();
896                                    }
897    
898                                    ServiceContextThreadLocal.popServiceContext();
899                            }
900                    }
901                    else if (lifecycle.equals(PortletRequest.RENDER_PHASE) ||
902                                     lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
903    
904                            PortalUtil.updateWindowState(
905                                    portletId, user, layout, windowState, request);
906    
907                            PortalUtil.updatePortletMode(
908                                    portletId, user, layout, portletMode, request);
909                    }
910    
911                    if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
912                            PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
913    
914                            String portletPrimaryKey = PortletPermissionUtil.getPrimaryKey(
915                                    layout.getPlid(), portletId);
916    
917                            portletDisplay.setId(portletId);
918                            portletDisplay.setRootPortletId(portlet.getRootPortletId());
919                            portletDisplay.setInstanceId(portlet.getInstanceId());
920                            portletDisplay.setResourcePK(portletPrimaryKey);
921                            portletDisplay.setPortletName(portletConfig.getPortletName());
922                            portletDisplay.setNamespace(
923                                    PortalUtil.getPortletNamespace(portletId));
924    
925                            WebDAVStorage webDAVStorage = portlet.getWebDAVStorageInstance();
926    
927                            if (webDAVStorage != null) {
928                                    portletDisplay.setWebDAVEnabled(true);
929                            }
930                            else {
931                                    portletDisplay.setWebDAVEnabled(false);
932                            }
933    
934                            ResourceRequestImpl resourceRequestImpl =
935                                    ResourceRequestFactory.create(
936                                            request, portlet, invokerPortlet, portletContext,
937                                            windowState, portletMode, portletPreferences,
938                                            layout.getPlid());
939    
940                            ResourceResponseImpl resourceResponseImpl =
941                                    ResourceResponseFactory.create(
942                                            resourceRequestImpl, response, portletId, companyId);
943    
944                            resourceRequestImpl.defineObjects(
945                                    portletConfig, resourceResponseImpl);
946    
947                            try {
948                                    ServiceContext serviceContext =
949                                            ServiceContextFactory.getInstance(resourceRequestImpl);
950    
951                                    ServiceContextThreadLocal.pushServiceContext(serviceContext);
952    
953                                    boolean access = PortletPermissionUtil.hasAccessPermission(
954                                            permissionChecker, scopeGroupId, layout, portlet,
955                                            portletMode);
956    
957                                    if (access) {
958                                            invokerPortlet.serveResource(
959                                                    resourceRequestImpl, resourceResponseImpl);
960                                    }
961                            }
962                            finally {
963                                    ServiceContextThreadLocal.popServiceContext();
964                            }
965                    }
966    
967                    return portlet;
968            }
969    
970            protected void processPublicRenderParameters(
971                    HttpServletRequest request, Layout layout, Portlet portlet) {
972    
973                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
974                            WebKeys.THEME_DISPLAY);
975    
976                    Map<String, String[]> publicRenderParameters =
977                            PublicRenderParametersPool.get(request, layout.getPlid());
978    
979                    Enumeration<String> enu = request.getParameterNames();
980    
981                    while (enu.hasMoreElements()) {
982                            String name = enu.nextElement();
983    
984                            String[] values = request.getParameterValues(name);
985    
986                            QName qName = PortletQNameUtil.getQName(name);
987    
988                            if (qName == null) {
989                                    continue;
990                            }
991    
992                            PublicRenderParameter publicRenderParameter =
993                                    portlet.getPublicRenderParameter(
994                                            qName.getNamespaceURI(), qName.getLocalPart());
995    
996                            if (publicRenderParameter == null) {
997                                    continue;
998                            }
999    
1000                            String publicRenderParameterName =
1001                                    PortletQNameUtil.getPublicRenderParameterName(qName);
1002    
1003                            if (name.startsWith(
1004                                            PortletQName.PUBLIC_RENDER_PARAMETER_NAMESPACE)) {
1005    
1006                                    if (themeDisplay.isLifecycleAction()) {
1007                                            String[] oldValues = publicRenderParameters.get(
1008                                                    publicRenderParameterName);
1009    
1010                                            if ((oldValues != null) && (oldValues.length != 0)) {
1011                                                    values = ArrayUtil.append(values, oldValues);
1012                                            }
1013                                    }
1014    
1015                                    publicRenderParameters.put(publicRenderParameterName, values);
1016                            }
1017                            else {
1018                                    publicRenderParameters.remove(publicRenderParameterName);
1019                            }
1020                    }
1021            }
1022    
1023            protected void redirectActionURL(
1024                            HttpServletRequest request, HttpServletResponse response,
1025                            ActionResponseImpl actionResponseImpl, Portlet portlet)
1026                    throws Exception {
1027    
1028                    ActionRequestImpl actionRequestImpl =
1029                            (ActionRequestImpl)request.getAttribute(
1030                                    JavaConstants.JAVAX_PORTLET_REQUEST);
1031    
1032                    Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
1033    
1034                    PortletURL portletURL = new PortletURLImpl(
1035                            actionRequestImpl, actionRequestImpl.getPortletName(),
1036                            layout.getPlid(), PortletRequest.RENDER_PHASE);
1037    
1038                    Map<String, String[]> renderParameters =
1039                            actionResponseImpl.getRenderParameterMap();
1040    
1041                    for (Map.Entry<String, String[]> entry : renderParameters.entrySet()) {
1042                            String key = entry.getKey();
1043                            String[] value = entry.getValue();
1044    
1045                            portletURL.setParameter(key, value);
1046                    }
1047    
1048                    response.sendRedirect(portletURL.toString());
1049            }
1050    
1051            protected void renderExclusive(
1052                            HttpServletRequest request, HttpServletResponse response,
1053                            ThemeDisplay themeDisplay)
1054                    throws Exception {
1055    
1056                    RenderRequestImpl renderRequestImpl =
1057                            (RenderRequestImpl)request.getAttribute(
1058                                    JavaConstants.JAVAX_PORTLET_REQUEST);
1059    
1060                    RenderResponseImpl renderResponseImpl =
1061                            (RenderResponseImpl)request.getAttribute(
1062                                    JavaConstants.JAVAX_PORTLET_RESPONSE);
1063    
1064                    StringServletResponse stringResponse =
1065                            (StringServletResponse)renderRequestImpl.getAttribute(
1066                                    WebKeys.STRING_SERVLET_RESPONSE);
1067    
1068                    if (stringResponse == null) {
1069                            stringResponse = (StringServletResponse)
1070                                    renderResponseImpl.getHttpServletResponse();
1071    
1072                            Portlet portlet = processPortletRequest(
1073                                    request, response, PortletRequest.RENDER_PHASE);
1074    
1075                            InvokerPortlet invokerPortlet = PortletInstanceFactoryUtil.create(
1076                                    portlet, null);
1077    
1078                            invokerPortlet.render(renderRequestImpl, renderResponseImpl);
1079    
1080                            if (Validator.isNull(stringResponse.getString())) {
1081                                    stringResponse.setString(null);
1082                            }
1083                    }
1084    
1085                    renderResponseImpl.transferHeaders(response);
1086    
1087                    if (stringResponse.isCalledGetOutputStream()) {
1088                            UnsyncByteArrayOutputStream ubaos =
1089                                    stringResponse.getUnsyncByteArrayOutputStream();
1090    
1091                            InputStream is = new UnsyncByteArrayInputStream(
1092                                    ubaos.unsafeGetByteArray(), 0, ubaos.size());
1093    
1094                            ServletResponseUtil.sendFile(
1095                                    request, response, renderResponseImpl.getResourceName(), is,
1096                                    renderResponseImpl.getContentType());
1097                    }
1098                    else if (stringResponse.isCalledGetWriter()) {
1099                            byte[] content = stringResponse.getString().getBytes(
1100                                    StringPool.UTF8);
1101    
1102                            ServletResponseUtil.sendFile(
1103                                    request, response, renderResponseImpl.getResourceName(),
1104                                    content, renderResponseImpl.getContentType());
1105                    }
1106    
1107                    renderRequestImpl.cleanUp();
1108            }
1109    
1110            protected Event serializeEvent(
1111                    Event event, ClassLoader portletClassLoader) {
1112    
1113                    Serializable value = event.getValue();
1114    
1115                    if (value == null) {
1116                            return event;
1117                    }
1118    
1119                    Class<?> valueClass = value.getClass();
1120    
1121                    String valueClassName = valueClass.getName();
1122    
1123                    try {
1124                            Class<?> loadedValueClass = portletClassLoader.loadClass(
1125                                    valueClassName);
1126    
1127                            if (loadedValueClass.equals(valueClass)) {
1128                                    return event;
1129                            }
1130                    }
1131                    catch (ClassNotFoundException cnfe) {
1132                            if (_log.isWarnEnabled()) {
1133                                    _log.warn(
1134                                            portletClassLoader.toString() + " does not contain " +
1135                                                    valueClassName,
1136                                            cnfe);
1137                            }
1138                    }
1139    
1140                    EventImpl eventImpl = (EventImpl)event;
1141    
1142                    String base64Value = eventImpl.getBase64Value();
1143    
1144                    value = (Serializable)Base64.stringToObject(
1145                            base64Value, portletClassLoader);
1146    
1147                    return new EventImpl(event.getName(), event.getQName(), value);
1148            }
1149    
1150            private static Log _log = LogFactoryUtil.getLog(LayoutAction.class);
1151    
1152    }