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