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