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