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