1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.action;
24  
25  import com.liferay.portal.kernel.language.LanguageUtil;
26  import com.liferay.portal.kernel.log.Log;
27  import com.liferay.portal.kernel.log.LogFactoryUtil;
28  import com.liferay.portal.kernel.portlet.PortletModeFactory;
29  import com.liferay.portal.kernel.portlet.WindowStateFactory;
30  import com.liferay.portal.kernel.servlet.BrowserSnifferUtil;
31  import com.liferay.portal.kernel.servlet.HttpHeaders;
32  import com.liferay.portal.kernel.servlet.StringServletResponse;
33  import com.liferay.portal.kernel.upload.UploadServletRequest;
34  import com.liferay.portal.kernel.util.ContentTypes;
35  import com.liferay.portal.kernel.util.HttpUtil;
36  import com.liferay.portal.kernel.util.JavaConstants;
37  import com.liferay.portal.kernel.util.MapUtil;
38  import com.liferay.portal.kernel.util.ParamUtil;
39  import com.liferay.portal.kernel.util.StringPool;
40  import com.liferay.portal.kernel.util.Validator;
41  import com.liferay.portal.model.Layout;
42  import com.liferay.portal.model.LayoutConstants;
43  import com.liferay.portal.model.LayoutTypePortlet;
44  import com.liferay.portal.model.Portlet;
45  import com.liferay.portal.model.PortletPreferencesIds;
46  import com.liferay.portal.model.User;
47  import com.liferay.portal.service.PortletLocalServiceUtil;
48  import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
49  import com.liferay.portal.service.permission.PortletPermissionUtil;
50  import com.liferay.portal.struts.ActionConstants;
51  import com.liferay.portal.struts.StrutsUtil;
52  import com.liferay.portal.theme.PortletDisplay;
53  import com.liferay.portal.theme.ThemeDisplay;
54  import com.liferay.portal.upload.UploadServletRequestImpl;
55  import com.liferay.portal.util.PortalUtil;
56  import com.liferay.portal.util.PropsValues;
57  import com.liferay.portal.util.WebKeys;
58  import com.liferay.portlet.ActionRequestFactory;
59  import com.liferay.portlet.ActionRequestImpl;
60  import com.liferay.portlet.ActionResponseFactory;
61  import com.liferay.portlet.ActionResponseImpl;
62  import com.liferay.portlet.EventRequestFactory;
63  import com.liferay.portlet.EventRequestImpl;
64  import com.liferay.portlet.EventResponseFactory;
65  import com.liferay.portlet.EventResponseImpl;
66  import com.liferay.portlet.InvokerPortlet;
67  import com.liferay.portlet.InvokerPortletImpl;
68  import com.liferay.portlet.PortletConfigFactory;
69  import com.liferay.portlet.PortletInstanceFactory;
70  import com.liferay.portlet.PortletPreferencesFactoryUtil;
71  import com.liferay.portlet.PortletRequestImpl;
72  import com.liferay.portlet.PortletURLImpl;
73  import com.liferay.portlet.RenderParametersPool;
74  import com.liferay.portlet.RenderRequestFactory;
75  import com.liferay.portlet.RenderRequestImpl;
76  import com.liferay.portlet.RenderResponseFactory;
77  import com.liferay.portlet.RenderResponseImpl;
78  import com.liferay.portlet.ResourceRequestFactory;
79  import com.liferay.portlet.ResourceRequestImpl;
80  import com.liferay.portlet.ResourceResponseFactory;
81  import com.liferay.portlet.ResourceResponseImpl;
82  import com.liferay.portlet.StateAwareResponseImpl;
83  import com.liferay.util.servlet.ServletResponseUtil;
84  
85  import java.io.ByteArrayInputStream;
86  import java.io.InputStream;
87  
88  import java.util.HashMap;
89  import java.util.List;
90  import java.util.Map;
91  
92  import javax.portlet.Event;
93  import javax.portlet.PortletConfig;
94  import javax.portlet.PortletContext;
95  import javax.portlet.PortletException;
96  import javax.portlet.PortletMode;
97  import javax.portlet.PortletPreferences;
98  import javax.portlet.PortletRequest;
99  import javax.portlet.PortletResponse;
100 import javax.portlet.PortletURL;
101 import javax.portlet.UnavailableException;
102 import javax.portlet.WindowState;
103 
104 import javax.servlet.RequestDispatcher;
105 import javax.servlet.ServletContext;
106 import javax.servlet.http.HttpServletRequest;
107 import javax.servlet.http.HttpServletResponse;
108 import javax.servlet.http.HttpSession;
109 
110 import javax.xml.namespace.QName;
111 
112 import org.apache.struts.action.Action;
113 import org.apache.struts.action.ActionForm;
114 import org.apache.struts.action.ActionForward;
115 import org.apache.struts.action.ActionMapping;
116 
117 /**
118  * <a href="LayoutAction.java.html"><b><i>View Source</i></b></a>
119  *
120  * @author Brian Wing Shun Chan
121  *
122  */
123 public class LayoutAction extends Action {
124 
125     public ActionForward execute(
126             ActionMapping mapping, ActionForm form, HttpServletRequest request,
127             HttpServletResponse response)
128         throws Exception {
129 
130         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
131             WebKeys.THEME_DISPLAY);
132 
133         Layout layout = themeDisplay.getLayout();
134 
135         Boolean layoutDefault = (Boolean)request.getAttribute(
136             WebKeys.LAYOUT_DEFAULT);
137 
138         if ((layoutDefault != null) && (layoutDefault.booleanValue())) {
139             Layout requestedLayout =
140                 (Layout)request.getAttribute(WebKeys.REQUESTED_LAYOUT);
141 
142             if (requestedLayout != null) {
143                 String redirectParam = "redirect";
144 
145                 String authLoginURL = PortalUtil.getCommunityLoginURL(
146                     themeDisplay);
147 
148                 if (Validator.isNull(authLoginURL)) {
149                     authLoginURL = PropsValues.AUTH_LOGIN_URL;
150                 }
151 
152                 if (Validator.isNotNull(PropsValues.AUTH_LOGIN_PORTLET_NAME) &&
153                     Validator.isNotNull(authLoginURL)) {
154 
155                     redirectParam =
156                         PortalUtil.getPortletNamespace(
157                             PropsValues.AUTH_LOGIN_PORTLET_NAME) +
158                         redirectParam;
159                 }
160 
161                 String url = PortalUtil.getLayoutURL(
162                     requestedLayout, themeDisplay);
163 
164                 String redirect = HttpUtil.addParameter(
165                     themeDisplay.getURLSignIn(), redirectParam, url);
166 
167                 if (_log.isDebugEnabled()) {
168                     _log.debug("Redirect requested layout to " + redirect);
169                 }
170 
171                 response.sendRedirect(redirect);
172             }
173             else {
174                 String redirect = PortalUtil.getLayoutURL(layout, themeDisplay);
175 
176                 if (_log.isDebugEnabled()) {
177                     _log.debug("Redirect default layout to " + redirect);
178                 }
179 
180                 response.sendRedirect(redirect);
181             }
182 
183             return null;
184         }
185 
186         long plid = ParamUtil.getLong(request, "p_l_id");
187 
188         if (_log.isDebugEnabled()) {
189             _log.debug("p_l_id is " + plid);
190         }
191 
192         if (plid > 0) {
193             return processLayout(mapping, request, response, plid);
194         }
195         else {
196             try {
197                 forwardLayout(request);
198 
199                 return mapping.findForward(ActionConstants.COMMON_FORWARD_JSP);
200             }
201             catch (Exception e) {
202                 PortalUtil.sendError(e, request, response);
203 
204                 return null;
205             }
206         }
207     }
208 
209     protected void forwardLayout(HttpServletRequest request) throws Exception {
210         Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
211 
212         long plid = LayoutConstants.DEFAULT_PLID;
213 
214         String layoutFriendlyURL = null;
215 
216         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
217             WebKeys.THEME_DISPLAY);
218 
219         if (layout != null) {
220             plid = layout.getPlid();
221 
222             layoutFriendlyURL = PortalUtil.getLayoutFriendlyURL(
223                 layout, themeDisplay);
224         }
225 
226         String forwardURL = layoutFriendlyURL;
227 
228         if (Validator.isNull(forwardURL)) {
229             forwardURL =
230                 themeDisplay.getPathMain() + "/portal/layout?p_l_id=" + plid;
231 
232             if (Validator.isNotNull(themeDisplay.getDoAsUserId())) {
233                 forwardURL = HttpUtil.addParameter(
234                     forwardURL, "doAsUserId", themeDisplay.getDoAsUserId());
235             }
236         }
237 
238         if (_log.isDebugEnabled()) {
239             _log.debug("Forward layout to " + forwardURL);
240         }
241 
242         request.setAttribute(WebKeys.FORWARD_URL, forwardURL);
243     }
244 
245     protected void includeLayoutContent(
246             HttpServletRequest request, HttpServletResponse response,
247             ThemeDisplay themeDisplay, Layout layout)
248         throws Exception {
249 
250         ServletContext servletContext = (ServletContext)request.getAttribute(
251             WebKeys.CTX);
252 
253         String path = StrutsUtil.TEXT_HTML_DIR;
254 
255         if (BrowserSnifferUtil.isWap(request)) {
256             path = StrutsUtil.TEXT_WAP_DIR;
257         }
258 
259         // Manually check the p_p_id. See LEP-1724.
260 
261         if (themeDisplay.isStateExclusive() ||
262             Validator.isNotNull(ParamUtil.getString(request, "p_p_id"))) {
263 
264             if (layout.getType().equals(LayoutConstants.TYPE_PANEL)) {
265                 path += "/portal/layout/view/panel.jsp";
266             }
267             else {
268                 path += "/portal/layout/view/portlet.jsp";
269             }
270         }
271         else {
272             path += PortalUtil.getLayoutViewPage(layout);
273         }
274 
275         RequestDispatcher requestDispatcher =
276             servletContext.getRequestDispatcher(path);
277 
278         StringServletResponse stringResponse = new StringServletResponse(
279             response);
280 
281         requestDispatcher.include(request, stringResponse);
282 
283         request.setAttribute(
284             WebKeys.LAYOUT_CONTENT, stringResponse.getString());
285     }
286 
287     protected void processEvent(
288             PortletRequestImpl portletRequestImpl,
289             StateAwareResponseImpl stateAwareResponseImpl, Portlet portlet,
290             List<Portlet> portlets, Event event)
291         throws Exception {
292 
293         HttpServletRequest request = portletRequestImpl.getHttpServletRequest();
294         HttpServletResponse response =
295             stateAwareResponseImpl.getHttpServletResponse();
296         HttpSession session = request.getSession();
297 
298         String portletId = portlet.getPortletId();
299 
300         ServletContext servletContext =
301             (ServletContext)request.getAttribute(WebKeys.CTX);
302 
303         InvokerPortlet invokerPortlet = PortletInstanceFactory.create(
304             portlet, servletContext);
305 
306         PortletConfig portletConfig = PortletConfigFactory.create(
307             portlet, servletContext);
308         PortletContext portletContext = portletConfig.getPortletContext();
309 
310         WindowState windowState = portletRequestImpl.getWindowState();
311         PortletMode portletMode = portletRequestImpl.getPortletMode();
312 
313         User user = stateAwareResponseImpl.getUser();
314         Layout layout = stateAwareResponseImpl.getLayout();
315 
316         PortletPreferences portletPreferences =
317             portletRequestImpl.getPreferencesImpl();
318 
319         EventRequestImpl eventRequestImpl = EventRequestFactory.create(
320             request, portlet, invokerPortlet, portletContext, windowState,
321             portletMode, portletPreferences, layout.getPlid());
322 
323         eventRequestImpl.setEvent(event);
324 
325         EventResponseImpl eventResponseImpl = EventResponseFactory.create(
326             eventRequestImpl, response, portletId, user, layout, windowState,
327             portletMode);
328 
329         eventRequestImpl.defineObjects(portletConfig, eventResponseImpl);
330 
331         try {
332             try {
333                 InvokerPortletImpl.clearResponse(
334                     session, layout.getPrimaryKey(), portletId,
335                     LanguageUtil.getLanguageId(eventRequestImpl));
336 
337                 invokerPortlet.processEvent(
338                     eventRequestImpl, eventResponseImpl);
339 
340                 if (eventResponseImpl.isCalledSetRenderParameter()) {
341                     Map<String, String[]> renderParameterMap =
342                         new HashMap<String, String[]>();
343 
344                     MapUtil.copy(
345                         eventResponseImpl.getRenderParameterMap(),
346                         renderParameterMap);
347 
348                     RenderParametersPool.put(
349                         request, layout.getPlid(), portletId,
350                         renderParameterMap);
351                 }
352             }
353             catch (UnavailableException ue) {
354                 throw ue;
355             }
356             catch (PortletException pe) {
357                 eventResponseImpl.setWindowState(windowState);
358                 eventResponseImpl.setPortletMode(portletMode);
359             }
360 
361             processEvents(eventRequestImpl, eventResponseImpl, portlets);
362         }
363         finally {
364             EventRequestFactory.recycle(eventRequestImpl);
365             EventResponseFactory.recycle(eventResponseImpl);
366         }
367     }
368 
369     protected void processEvents(
370             PortletRequestImpl portletRequestImpl,
371             StateAwareResponseImpl stateAwareResponseImpl,
372             List<Portlet> portlets)
373         throws Exception {
374 
375         List<Event> events = stateAwareResponseImpl.getEvents();
376 
377         if (events.size() == 0) {
378             return;
379         }
380 
381         for (Event event : events) {
382             QName qName = event.getQName();
383 
384             for (Portlet portlet : portlets) {
385                 QName processingQName = portlet.getProcessingEvent(
386                     qName.getNamespaceURI(), qName.getLocalPart());
387 
388                 if (processingQName != null) {
389                     processEvent(
390                         portletRequestImpl, stateAwareResponseImpl, portlet,
391                         portlets, event);
392                 }
393             }
394         }
395     }
396 
397     protected ActionForward processLayout(
398             ActionMapping mapping, HttpServletRequest request,
399             HttpServletResponse response, long plid)
400         throws Exception {
401 
402         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
403             WebKeys.THEME_DISPLAY);
404 
405         try {
406             Layout layout = themeDisplay.getLayout();
407 
408             boolean resetLayout = ParamUtil.getBoolean(
409                 request, "p_l_reset", PropsValues.LAYOUT_DEFAULT_P_L_RESET);
410 
411             if (!PropsValues.TCK_URL && resetLayout) {
412                 RenderParametersPool.clear(request, plid);
413             }
414 
415             if (themeDisplay.isLifecycleAction()) {
416                 Portlet portlet = processPortletRequest(
417                     request, response, PortletRequest.ACTION_PHASE);
418 
419                 if (portlet != null) {
420                     ActionResponseImpl actionResponseImpl =
421                         (ActionResponseImpl)request.getAttribute(
422                             JavaConstants.JAVAX_PORTLET_RESPONSE);
423 
424                     String redirectLocation =
425                         actionResponseImpl.getRedirectLocation();
426 
427                     if (Validator.isNotNull(redirectLocation)) {
428                         response.sendRedirect(redirectLocation);
429 
430                         return null;
431                     }
432 
433                     if (portlet.isActionURLRedirect()) {
434                         redirectActionURL(
435                             request, response, actionResponseImpl, portlet);
436 
437                         return null;
438                     }
439                 }
440             }
441             else if (themeDisplay.isLifecycleRender()) {
442                 processPortletRequest(
443                     request, response, PortletRequest.RENDER_PHASE);
444             }
445 
446             if (themeDisplay.isLifecycleResource()) {
447                 processPortletRequest(
448                     request, response, PortletRequest.RESOURCE_PHASE);
449 
450                 return null;
451             }
452             else {
453                 if (layout != null) {
454 
455                     // Include layout content before the page loads because
456                     // portlets on the page can set the page title and page
457                     // subtitle
458 
459                     includeLayoutContent(
460                         request, response, themeDisplay, layout);
461 
462                     if (themeDisplay.isStateExclusive()) {
463                         renderExclusive(request, response, themeDisplay);
464 
465                         return null;
466                     }
467                 }
468 
469                 return mapping.findForward("portal.layout");
470             }
471         }
472         catch (Exception e) {
473             PortalUtil.sendError(e, request, response);
474 
475             return null;
476         }
477         finally {
478             PortletRequest portletRequest =
479                 (PortletRequest)request.getAttribute(
480                     JavaConstants.JAVAX_PORTLET_REQUEST);
481 
482             try {
483                 if (portletRequest != null) {
484                     if (themeDisplay.isLifecycleAction()) {
485                         ActionRequestImpl actionRequestImpl =
486                             (ActionRequestImpl)portletRequest;
487 
488                         ActionRequestFactory.recycle(actionRequestImpl);
489                     }
490                     else if (themeDisplay.isLifecycleRender()) {
491                         RenderRequestImpl renderRequestImpl =
492                             (RenderRequestImpl)portletRequest;
493 
494                         RenderRequestFactory.recycle(renderRequestImpl);
495                     }
496                     else if (themeDisplay.isLifecycleResource()) {
497                         ResourceRequestImpl resourceRequestImpl =
498                             (ResourceRequestImpl)portletRequest;
499 
500                         ResourceRequestFactory.recycle(resourceRequestImpl);
501                     }
502                 }
503             }
504             catch (Exception e) {
505                 _log.error(e);
506             }
507 
508             request.removeAttribute(JavaConstants.JAVAX_PORTLET_REQUEST);
509 
510             PortletResponse portletResponse =
511                 (PortletResponse)request.getAttribute(
512                     JavaConstants.JAVAX_PORTLET_RESPONSE);
513 
514             try {
515                 if (portletResponse != null) {
516                     if (themeDisplay.isLifecycleAction()) {
517                         ActionResponseImpl actionResponseImpl =
518                             (ActionResponseImpl)portletResponse;
519 
520                         ActionResponseFactory.recycle(actionResponseImpl);
521                     }
522                     else if (themeDisplay.isLifecycleRender()) {
523                         RenderResponseImpl renderResponseImpl =
524                             (RenderResponseImpl)portletResponse;
525 
526                         RenderResponseFactory.recycle(renderResponseImpl);
527                     }
528                     else if (themeDisplay.isLifecycleResource()) {
529                         ResourceResponseImpl resourceResponseImpl =
530                             (ResourceResponseImpl)portletResponse;
531 
532                         ResourceResponseFactory.recycle(resourceResponseImpl);
533                     }
534                 }
535             }
536             catch (Exception e) {
537                 _log.error(e);
538             }
539 
540             request.removeAttribute(JavaConstants.JAVAX_PORTLET_RESPONSE);
541         }
542     }
543 
544     protected Portlet processPortletRequest(
545             HttpServletRequest request, HttpServletResponse response,
546             String lifecycle)
547         throws Exception {
548 
549         HttpSession session = request.getSession();
550 
551         long companyId = PortalUtil.getCompanyId(request);
552         User user = PortalUtil.getUser(request);
553         Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
554 
555         String portletId = ParamUtil.getString(request, "p_p_id");
556 
557         if (Validator.isNull(portletId)) {
558             return null;
559         }
560 
561         Portlet portlet = PortletLocalServiceUtil.getPortletById(
562             companyId, portletId);
563 
564         if (portlet == null) {
565             return null;
566         }
567 
568         ServletContext servletContext = (ServletContext)request.getAttribute(
569             WebKeys.CTX);
570 
571         InvokerPortlet invokerPortlet = PortletInstanceFactory.create(
572             portlet, servletContext);
573 
574         if (user != null) {
575             InvokerPortletImpl.clearResponse(
576                 session, layout.getPrimaryKey(), portletId,
577                 LanguageUtil.getLanguageId(request));
578         }
579 
580         PortletConfig portletConfig = PortletConfigFactory.create(
581             portlet, servletContext);
582         PortletContext portletContext = portletConfig.getPortletContext();
583 
584         WindowState windowState = WindowStateFactory.getWindowState(
585             ParamUtil.getString(request, "p_p_state"));
586 
587         PortletMode portletMode = PortletModeFactory.getPortletMode(
588             ParamUtil.getString(request, "p_p_mode"));
589 
590         PortletPreferencesIds portletPreferencesIds =
591             PortletPreferencesFactoryUtil.getPortletPreferencesIds(
592                 request, portletId);
593 
594         PortletPreferences portletPreferences =
595             PortletPreferencesLocalServiceUtil.getPreferences(
596                 portletPreferencesIds);
597 
598         if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
599             String contentType = request.getHeader(HttpHeaders.CONTENT_TYPE);
600 
601             if (_log.isDebugEnabled()) {
602                 _log.debug("Content type " + contentType);
603             }
604 
605             UploadServletRequest uploadRequest = null;
606 
607             try {
608                 if ((contentType != null) &&
609                     (contentType.startsWith(
610                         ContentTypes.MULTIPART_FORM_DATA))) {
611 
612                     if (!invokerPortlet.getPortletConfig().isWARFile() ||
613                         invokerPortlet.isStrutsPortlet()) {
614 
615                         uploadRequest = new UploadServletRequestImpl(request);
616 
617                         request = uploadRequest;
618                     }
619                 }
620 
621                 ActionRequestImpl actionRequestImpl =
622                     ActionRequestFactory.create(
623                         request, portlet, invokerPortlet, portletContext,
624                         windowState, portletMode, portletPreferences,
625                         layout.getPlid());
626 
627                 ActionResponseImpl actionResponseImpl =
628                     ActionResponseFactory.create(
629                         actionRequestImpl, response, portletId, user, layout,
630                         windowState, portletMode);
631 
632                 actionRequestImpl.defineObjects(
633                     portletConfig, actionResponseImpl);
634 
635                 invokerPortlet.processAction(
636                     actionRequestImpl, actionResponseImpl);
637 
638                 actionResponseImpl.transferHeaders(response);
639 
640                 RenderParametersPool.put(
641                     request, layout.getPlid(), portletId,
642                     actionResponseImpl.getRenderParameterMap());
643 
644                 if (actionResponseImpl.getEvents().size() > 0) {
645                     if (layout.getType().equals(LayoutConstants.TYPE_PORTLET)) {
646                         LayoutTypePortlet layoutTypePortlet =
647                             (LayoutTypePortlet)layout.getLayoutType();
648 
649                         List<Portlet> portlets =
650                             layoutTypePortlet.getPortlets();
651 
652                         processEvents(
653                             actionRequestImpl, actionResponseImpl, portlets);
654 
655                         actionRequestImpl.defineObjects(
656                             portletConfig, actionResponseImpl);
657                     }
658                 }
659             }
660             finally {
661                 if (uploadRequest != null) {
662                     uploadRequest.cleanUp();
663                 }
664             }
665         }
666         else if (lifecycle.equals(PortletRequest.RENDER_PHASE) ||
667                  lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
668 
669             PortalUtil.updateWindowState(
670                 portletId, user, layout, windowState, request);
671 
672             PortalUtil.updatePortletMode(
673                 portletId, user, layout, portletMode, request);
674         }
675 
676         if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
677             ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
678                 WebKeys.THEME_DISPLAY);
679 
680             PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
681 
682             String portletPrimaryKey = PortletPermissionUtil.getPrimaryKey(
683                 layout.getPlid(), portletId);
684 
685             portletDisplay.setId(portletId);
686             portletDisplay.setRootPortletId(portlet.getRootPortletId());
687             portletDisplay.setInstanceId(portlet.getInstanceId());
688             portletDisplay.setResourcePK(portletPrimaryKey);
689             portletDisplay.setPortletName(portletConfig.getPortletName());
690             portletDisplay.setNamespace(
691                 PortalUtil.getPortletNamespace(portletId));
692 
693             ResourceRequestImpl resourceRequestImpl =
694                 ResourceRequestFactory.create(
695                     request, portlet, invokerPortlet, portletContext,
696                     windowState, portletMode, portletPreferences,
697                     layout.getPlid());
698 
699             ResourceResponseImpl resourceResponseImpl =
700                 ResourceResponseFactory.create(
701                     resourceRequestImpl, response, portletId, companyId);
702 
703             resourceRequestImpl.defineObjects(
704                 portletConfig, resourceResponseImpl);
705 
706             invokerPortlet.serveResource(
707                 resourceRequestImpl, resourceResponseImpl);
708         }
709 
710         return portlet;
711     }
712 
713     protected void redirectActionURL(
714             HttpServletRequest request, HttpServletResponse response,
715             ActionResponseImpl actionResponseImpl, Portlet portlet)
716         throws Exception {
717 
718         ActionRequestImpl actionRequestImpl =
719             (ActionRequestImpl)request.getAttribute(
720                 JavaConstants.JAVAX_PORTLET_REQUEST);
721 
722         Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
723 
724         PortletURL portletURL = new PortletURLImpl(
725             actionRequestImpl, actionRequestImpl.getPortletName(),
726             layout.getLayoutId(), PortletRequest.RENDER_PHASE);
727 
728         Map<String, String[]> renderParameters =
729             actionResponseImpl.getRenderParameterMap();
730 
731         for (Map.Entry<String, String[]> entry : renderParameters.entrySet()) {
732             String key = entry.getKey();
733             String[] value = entry.getValue();
734 
735             portletURL.setParameter(key, value);
736         }
737 
738         response.sendRedirect(portletURL.toString());
739     }
740 
741     protected void renderExclusive(
742             HttpServletRequest request, HttpServletResponse response,
743             ThemeDisplay themeDisplay)
744         throws Exception {
745 
746         RenderRequestImpl renderRequestImpl =
747             (RenderRequestImpl)request.getAttribute(
748                 JavaConstants.JAVAX_PORTLET_REQUEST);
749 
750         RenderResponseImpl renderResponseImpl =
751             (RenderResponseImpl)request.getAttribute(
752                 JavaConstants.JAVAX_PORTLET_RESPONSE);
753 
754         StringServletResponse stringResponse =
755             (StringServletResponse)renderRequestImpl.getAttribute(
756                 WebKeys.STRING_SERVLET_RESPONSE);
757 
758         renderResponseImpl.transferHeaders(response);
759 
760         if (stringResponse.isCalledGetOutputStream()) {
761             InputStream is = new ByteArrayInputStream(
762                 stringResponse.getByteArrayMaker().toByteArray());
763 
764             ServletResponseUtil.sendFile(
765                 response, renderResponseImpl.getResourceName(), is,
766                 renderResponseImpl.getContentType());
767         }
768         else {
769             byte[] content = stringResponse.getString().getBytes(
770                 StringPool.UTF8);
771 
772             ServletResponseUtil.sendFile(
773                 response, renderResponseImpl.getResourceName(), content,
774                 renderResponseImpl.getContentType());
775         }
776 
777         RenderRequestFactory.recycle(renderRequestImpl);
778         RenderResponseFactory.recycle(renderResponseImpl);
779     }
780 
781     private static Log _log = LogFactoryUtil.getLog(LayoutAction.class);
782 
783 }