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.auth.AuthTokenUtil;
52  import com.liferay.portal.security.permission.ActionKeys;
53  import com.liferay.portal.service.LayoutLocalServiceUtil;
54  import com.liferay.portal.service.PortletLocalServiceUtil;
55  import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
56  import com.liferay.portal.service.permission.PortletPermissionUtil;
57  import com.liferay.portal.struts.ActionConstants;
58  import com.liferay.portal.struts.StrutsUtil;
59  import com.liferay.portal.theme.PortletDisplay;
60  import com.liferay.portal.theme.ThemeDisplay;
61  import com.liferay.portal.upload.UploadServletRequestImpl;
62  import com.liferay.portal.util.PortalUtil;
63  import com.liferay.portal.util.PrefsPropsUtil;
64  import com.liferay.portal.util.PropsValues;
65  import com.liferay.portal.util.WebKeys;
66  import com.liferay.portlet.ActionRequestFactory;
67  import com.liferay.portlet.ActionRequestImpl;
68  import com.liferay.portlet.ActionResponseFactory;
69  import com.liferay.portlet.ActionResponseImpl;
70  import com.liferay.portlet.EventImpl;
71  import com.liferay.portlet.EventRequestFactory;
72  import com.liferay.portlet.EventRequestImpl;
73  import com.liferay.portlet.EventResponseFactory;
74  import com.liferay.portlet.EventResponseImpl;
75  import com.liferay.portlet.InvokerPortlet;
76  import com.liferay.portlet.InvokerPortletImpl;
77  import com.liferay.portlet.PortletConfigFactory;
78  import com.liferay.portlet.PortletConfigImpl;
79  import com.liferay.portlet.PortletInstanceFactoryUtil;
80  import com.liferay.portlet.PortletPreferencesFactoryUtil;
81  import com.liferay.portlet.PortletQName;
82  import com.liferay.portlet.PortletQNameUtil;
83  import com.liferay.portlet.PortletRequestImpl;
84  import com.liferay.portlet.PortletURLImpl;
85  import com.liferay.portlet.PublicRenderParametersPool;
86  import com.liferay.portlet.RenderParametersPool;
87  import com.liferay.portlet.RenderRequestImpl;
88  import com.liferay.portlet.RenderResponseImpl;
89  import com.liferay.portlet.ResourceRequestFactory;
90  import com.liferay.portlet.ResourceRequestImpl;
91  import com.liferay.portlet.ResourceResponseFactory;
92  import com.liferay.portlet.ResourceResponseImpl;
93  import com.liferay.portlet.StateAwareResponseImpl;
94  import com.liferay.portlet.login.util.LoginUtil;
95  import com.liferay.util.servlet.ServletResponseUtil;
96  
97  import java.io.InputStream;
98  import java.io.Serializable;
99  
100 import java.util.ArrayList;
101 import java.util.Enumeration;
102 import java.util.HashMap;
103 import java.util.List;
104 import java.util.Map;
105 
106 import javax.portlet.Event;
107 import javax.portlet.PortletConfig;
108 import javax.portlet.PortletContext;
109 import javax.portlet.PortletMode;
110 import javax.portlet.PortletPreferences;
111 import javax.portlet.PortletRequest;
112 import javax.portlet.PortletURL;
113 import javax.portlet.UnavailableException;
114 import javax.portlet.WindowState;
115 
116 import javax.servlet.RequestDispatcher;
117 import javax.servlet.ServletContext;
118 import javax.servlet.http.HttpServletRequest;
119 import javax.servlet.http.HttpServletResponse;
120 import javax.servlet.http.HttpSession;
121 
122 import org.apache.struts.action.Action;
123 import org.apache.struts.action.ActionForm;
124 import org.apache.struts.action.ActionForward;
125 import org.apache.struts.action.ActionMapping;
126 
127 /**
128  * <a href="LayoutAction.java.html"><b><i>View Source</i></b></a>
129  *
130  * @author Brian Wing Shun Chan
131  */
132 public class LayoutAction extends Action {
133 
134     public ActionForward execute(
135             ActionMapping mapping, ActionForm form, HttpServletRequest request,
136             HttpServletResponse response)
137         throws Exception {
138 
139         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
140             WebKeys.THEME_DISPLAY);
141 
142         Layout layout = themeDisplay.getLayout();
143 
144         Boolean layoutDefault = (Boolean)request.getAttribute(
145             WebKeys.LAYOUT_DEFAULT);
146 
147         if ((layoutDefault != null) && (layoutDefault.booleanValue())) {
148             Layout requestedLayout = (Layout)request.getAttribute(
149                 WebKeys.REQUESTED_LAYOUT);
150 
151             if (requestedLayout != null) {
152                 String redirectParam = "redirect";
153 
154                 if (Validator.isNotNull(PropsValues.AUTH_LOGIN_PORTLET_NAME)) {
155                     redirectParam =
156                         PortalUtil.getPortletNamespace(
157                             PropsValues.AUTH_LOGIN_PORTLET_NAME) +
158                         redirectParam;
159                 }
160 
161                 String authLoginURL = null;
162 
163                 if (PrefsPropsUtil.getBoolean(
164                         themeDisplay.getCompanyId(), PropsKeys.CAS_AUTH_ENABLED,
165                         PropsValues.CAS_AUTH_ENABLED)) {
166 
167                     authLoginURL = themeDisplay.getURLSignIn();
168                 }
169 
170                 if (Validator.isNull(authLoginURL)) {
171                     authLoginURL = PortalUtil.getCommunityLoginURL(
172                         themeDisplay);
173                 }
174 
175                 if (Validator.isNull(authLoginURL)) {
176                     authLoginURL = PropsValues.AUTH_LOGIN_URL;
177                 }
178 
179                 if (Validator.isNull(authLoginURL)) {
180                     PortletURL loginURL = LoginUtil.getLoginURL(
181                         request, themeDisplay.getPlid());
182 
183                     authLoginURL = loginURL.toString();
184                 }
185 
186                 String currentURL = PortalUtil.getCurrentURL(request);
187 
188                 authLoginURL = HttpUtil.setParameter(
189                     authLoginURL, redirectParam, currentURL);
190 
191                 if (_log.isDebugEnabled()) {
192                     _log.debug("Redirect requested layout to " + authLoginURL);
193                 }
194 
195                 response.sendRedirect(authLoginURL);
196             }
197             else {
198                 String redirect = PortalUtil.getLayoutURL(layout, themeDisplay);
199 
200                 if (_log.isDebugEnabled()) {
201                     _log.debug("Redirect default layout to " + redirect);
202                 }
203 
204                 response.sendRedirect(redirect);
205             }
206 
207             return null;
208         }
209 
210         long plid = ParamUtil.getLong(request, "p_l_id");
211 
212         if (_log.isDebugEnabled()) {
213             _log.debug("p_l_id is " + plid);
214         }
215 
216         if (plid > 0) {
217             return processLayout(mapping, request, response, plid);
218         }
219         else {
220             try {
221                 forwardLayout(request);
222 
223                 return mapping.findForward(ActionConstants.COMMON_FORWARD_JSP);
224             }
225             catch (Exception e) {
226                 PortalUtil.sendError(e, request, response);
227 
228                 return null;
229             }
230         }
231     }
232 
233     protected void forwardLayout(HttpServletRequest request) throws Exception {
234         Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
235 
236         long plid = LayoutConstants.DEFAULT_PLID;
237 
238         String layoutFriendlyURL = null;
239 
240         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
241             WebKeys.THEME_DISPLAY);
242 
243         if (layout != null) {
244             plid = layout.getPlid();
245 
246             layoutFriendlyURL = PortalUtil.getLayoutFriendlyURL(
247                 layout, themeDisplay);
248         }
249 
250         String forwardURL = layoutFriendlyURL;
251 
252         if (Validator.isNull(forwardURL)) {
253             forwardURL =
254                 themeDisplay.getPathMain() + "/portal/layout?p_l_id=" + plid;
255 
256             if (Validator.isNotNull(themeDisplay.getDoAsUserId())) {
257                 forwardURL = HttpUtil.addParameter(
258                     forwardURL, "doAsUserId", themeDisplay.getDoAsUserId());
259             }
260 
261             if (Validator.isNotNull(themeDisplay.getDoAsUserLanguageId())) {
262                 forwardURL = HttpUtil.addParameter(
263                     forwardURL, "doAsUserLanguageId",
264                     themeDisplay.getDoAsUserLanguageId());
265             }
266         }
267 
268         if (_log.isDebugEnabled()) {
269             _log.debug("Forward layout to " + forwardURL);
270         }
271 
272         request.setAttribute(WebKeys.FORWARD_URL, forwardURL);
273     }
274 
275     protected List<LayoutTypePortlet> getLayoutTypePortlets(
276             long groupId, boolean privateLayout)
277         throws Exception {
278 
279         List<LayoutTypePortlet> layoutTypePortlets =
280             new ArrayList<LayoutTypePortlet>();
281 
282         List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
283             groupId, privateLayout, LayoutConstants.TYPE_PORTLET);
284 
285         for (Layout layout : layouts) {
286             if (!layout.isTypePortlet()) {
287                 continue;
288             }
289 
290             LayoutTypePortlet layoutTypePortlet =
291                 (LayoutTypePortlet)layout.getLayoutType();
292 
293             layoutTypePortlets.add(layoutTypePortlet);
294         }
295 
296         return layoutTypePortlets;
297     }
298 
299     protected void includeLayoutContent(
300             HttpServletRequest request, HttpServletResponse response,
301             ThemeDisplay themeDisplay, Layout layout)
302         throws Exception {
303 
304         ServletContext servletContext = (ServletContext)request.getAttribute(
305             WebKeys.CTX);
306 
307         String path = StrutsUtil.TEXT_HTML_DIR;
308 
309         if (BrowserSnifferUtil.isWap(request)) {
310             path = StrutsUtil.TEXT_WAP_DIR;
311         }
312 
313         // Manually check the p_p_id. See LEP-1724.
314 
315         if (themeDisplay.isStateExclusive() ||
316             Validator.isNotNull(ParamUtil.getString(request, "p_p_id"))) {
317 
318             if (layout.isTypePanel()) {
319                 path += "/portal/layout/view/panel.jsp";
320             }
321             else if (layout.isTypeControlPanel()) {
322                 path += "/portal/layout/view/control_panel.jsp";
323             }
324             else {
325                 path += "/portal/layout/view/portlet.jsp";
326             }
327         }
328         else {
329             path += PortalUtil.getLayoutViewPage(layout);
330         }
331 
332         RequestDispatcher requestDispatcher =
333             servletContext.getRequestDispatcher(path);
334 
335         StringServletResponse stringResponse = new StringServletResponse(
336             response);
337 
338         requestDispatcher.include(request, stringResponse);
339 
340         request.setAttribute(
341             WebKeys.LAYOUT_CONTENT, stringResponse.getString());
342     }
343 
344     protected void processEvent(
345             PortletRequestImpl portletRequestImpl,
346             StateAwareResponseImpl stateAwareResponseImpl,
347             List<LayoutTypePortlet> layoutTypePortlets,
348             LayoutTypePortlet layoutTypePortlet, Portlet portlet, Event event)
349         throws Exception {
350 
351         HttpServletRequest request = portletRequestImpl.getHttpServletRequest();
352         HttpServletResponse response =
353             stateAwareResponseImpl.getHttpServletResponse();
354         HttpSession session = request.getSession();
355 
356         String portletId = portlet.getPortletId();
357 
358         ServletContext servletContext =
359             (ServletContext)request.getAttribute(WebKeys.CTX);
360 
361         InvokerPortlet invokerPortlet = PortletInstanceFactoryUtil.create(
362             portlet, servletContext);
363 
364         PortletConfig portletConfig = PortletConfigFactory.create(
365             portlet, servletContext);
366         PortletContext portletContext = portletConfig.getPortletContext();
367 
368         WindowState windowState = null;
369 
370         if (layoutTypePortlet.hasStateMaxPortletId(portletId)) {
371             windowState = WindowState.MAXIMIZED;
372         }
373         else if (layoutTypePortlet.hasStateMinPortletId(portletId)) {
374             windowState = WindowState.MINIMIZED;
375         }
376         else {
377             windowState = WindowState.NORMAL;
378         }
379 
380         PortletMode portletMode = null;
381 
382         if (layoutTypePortlet.hasModeAboutPortletId(portletId)) {
383             portletMode = LiferayPortletMode.ABOUT;
384         }
385         else if (layoutTypePortlet.hasModeConfigPortletId(portletId)) {
386             portletMode = LiferayPortletMode.CONFIG;
387         }
388         else if (layoutTypePortlet.hasModeEditPortletId(portletId)) {
389             portletMode = PortletMode.EDIT;
390         }
391         else if (layoutTypePortlet.hasModeEditDefaultsPortletId(portletId)) {
392             portletMode = LiferayPortletMode.EDIT_DEFAULTS;
393         }
394         else if (layoutTypePortlet.hasModeEditGuestPortletId(portletId)) {
395             portletMode = LiferayPortletMode.EDIT_GUEST;
396         }
397         else if (layoutTypePortlet.hasModeHelpPortletId(portletId)) {
398             portletMode = PortletMode.HELP;
399         }
400         else if (layoutTypePortlet.hasModePreviewPortletId(portletId)) {
401             portletMode = LiferayPortletMode.PREVIEW;
402         }
403         else if (layoutTypePortlet.hasModePrintPortletId(portletId)) {
404             portletMode = LiferayPortletMode.PRINT;
405         }
406         else {
407             portletMode = PortletMode.VIEW;
408         }
409 
410         User user = stateAwareResponseImpl.getUser();
411         Layout layout = stateAwareResponseImpl.getLayout();
412 
413         PortletPreferences portletPreferences =
414             portletRequestImpl.getPreferencesImpl();
415 
416         EventRequestImpl eventRequestImpl = EventRequestFactory.create(
417             request, portlet, invokerPortlet, portletContext, windowState,
418             portletMode, portletPreferences,
419             layoutTypePortlet.getLayout().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                 if (PropsValues.AUTH_TOKEN_CHECK_ENABLED &&
719                     invokerPortlet.isCheckAuthToken()) {
720 
721                     AuthTokenUtil.check(request);
722                 }
723 
724                 ActionRequestImpl actionRequestImpl =
725                     ActionRequestFactory.create(
726                         request, portlet, invokerPortlet, portletContext,
727                         windowState, portletMode, portletPreferences,
728                         layout.getPlid());
729 
730                 ActionResponseImpl actionResponseImpl =
731                     ActionResponseFactory.create(
732                         actionRequestImpl, response, portletId, user, layout,
733                         windowState, portletMode);
734 
735                 actionRequestImpl.defineObjects(
736                     portletConfig, actionResponseImpl);
737 
738                 invokerPortlet.processAction(
739                     actionRequestImpl, actionResponseImpl);
740 
741                 actionResponseImpl.transferHeaders(response);
742 
743                 RenderParametersPool.put(
744                     request, layout.getPlid(), portletId,
745                     actionResponseImpl.getRenderParameterMap());
746 
747                 List<LayoutTypePortlet> layoutTypePortlets = null;
748 
749                 if (!actionResponseImpl.getEvents().isEmpty()) {
750                     if (PropsValues.PORTLET_EVENT_DISTRIBUTION_LAYOUT_SET) {
751                         layoutTypePortlets = getLayoutTypePortlets(
752                             layout.getGroupId(), layout.isPrivateLayout());
753                     }
754                     else {
755                         if (layout.isTypePortlet()) {
756                             LayoutTypePortlet layoutTypePortlet =
757                                 (LayoutTypePortlet)layout.getLayoutType();
758 
759                             layoutTypePortlets =
760                                 new ArrayList<LayoutTypePortlet>();
761 
762                             layoutTypePortlets.add(layoutTypePortlet);
763                         }
764                     }
765 
766                     processEvents(
767                         actionRequestImpl, actionResponseImpl,
768                         layoutTypePortlets);
769 
770                     actionRequestImpl.defineObjects(
771                         portletConfig, actionResponseImpl);
772                 }
773             }
774             finally {
775                 if (uploadRequest != null) {
776                     uploadRequest.cleanUp();
777                 }
778             }
779         }
780         else if (lifecycle.equals(PortletRequest.RENDER_PHASE) ||
781                  lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
782 
783             PortalUtil.updateWindowState(
784                 portletId, user, layout, windowState, request);
785 
786             PortalUtil.updatePortletMode(
787                 portletId, user, layout, portletMode, request);
788         }
789 
790         if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
791             PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
792 
793             String portletPrimaryKey = PortletPermissionUtil.getPrimaryKey(
794                 layout.getPlid(), portletId);
795 
796             portletDisplay.setId(portletId);
797             portletDisplay.setRootPortletId(portlet.getRootPortletId());
798             portletDisplay.setInstanceId(portlet.getInstanceId());
799             portletDisplay.setResourcePK(portletPrimaryKey);
800             portletDisplay.setPortletName(portletConfig.getPortletName());
801             portletDisplay.setNamespace(
802                 PortalUtil.getPortletNamespace(portletId));
803 
804             ResourceRequestImpl resourceRequestImpl =
805                 ResourceRequestFactory.create(
806                     request, portlet, invokerPortlet, portletContext,
807                     windowState, portletMode, portletPreferences,
808                     layout.getPlid());
809 
810             ResourceResponseImpl resourceResponseImpl =
811                 ResourceResponseFactory.create(
812                     resourceRequestImpl, response, portletId, companyId);
813 
814             resourceRequestImpl.defineObjects(
815                 portletConfig, resourceResponseImpl);
816 
817             invokerPortlet.serveResource(
818                 resourceRequestImpl, resourceResponseImpl);
819         }
820 
821         return portlet;
822     }
823 
824     protected void processPublicRenderParameters(
825         HttpServletRequest request, Layout layout, Portlet portlet) {
826 
827         Map<String, String[]> publicRenderParameters =
828             PublicRenderParametersPool.get(request, layout.getPlid());
829 
830         Enumeration<String> enu = request.getParameterNames();
831 
832         while (enu.hasMoreElements()) {
833             String name = enu.nextElement();
834 
835             String[] values = request.getParameterValues(name);
836 
837             QName qName = PortletQNameUtil.getQName(name);
838 
839             if (qName == null) {
840                 continue;
841             }
842 
843             PublicRenderParameter publicRenderParameter =
844                 portlet.getPublicRenderParameter(
845                     qName.getNamespaceURI(), qName.getLocalPart());
846 
847             if (publicRenderParameter == null) {
848                 continue;
849             }
850 
851             if (name.startsWith(
852                     PortletQName.PUBLIC_RENDER_PARAMETER_NAMESPACE)) {
853 
854                 publicRenderParameters.put(
855                     PortletQNameUtil.getKey(qName), values);
856             }
857             else {
858                 publicRenderParameters.remove(PortletQNameUtil.getKey(qName));
859             }
860         }
861     }
862 
863     protected void redirectActionURL(
864             HttpServletRequest request, HttpServletResponse response,
865             ActionResponseImpl actionResponseImpl, Portlet portlet)
866         throws Exception {
867 
868         ActionRequestImpl actionRequestImpl =
869             (ActionRequestImpl)request.getAttribute(
870                 JavaConstants.JAVAX_PORTLET_REQUEST);
871 
872         Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
873 
874         PortletURL portletURL = new PortletURLImpl(
875             actionRequestImpl, actionRequestImpl.getPortletName(),
876             layout.getPlid(), PortletRequest.RENDER_PHASE);
877 
878         Map<String, String[]> renderParameters =
879             actionResponseImpl.getRenderParameterMap();
880 
881         for (Map.Entry<String, String[]> entry : renderParameters.entrySet()) {
882             String key = entry.getKey();
883             String[] value = entry.getValue();
884 
885             portletURL.setParameter(key, value);
886         }
887 
888         response.sendRedirect(portletURL.toString());
889     }
890 
891     protected void renderExclusive(
892             HttpServletRequest request, HttpServletResponse response,
893             ThemeDisplay themeDisplay)
894         throws Exception {
895 
896         RenderRequestImpl renderRequestImpl =
897             (RenderRequestImpl)request.getAttribute(
898                 JavaConstants.JAVAX_PORTLET_REQUEST);
899 
900         RenderResponseImpl renderResponseImpl =
901             (RenderResponseImpl)request.getAttribute(
902                 JavaConstants.JAVAX_PORTLET_RESPONSE);
903 
904         StringServletResponse stringResponse =
905             (StringServletResponse)renderRequestImpl.getAttribute(
906                 WebKeys.STRING_SERVLET_RESPONSE);
907 
908         renderResponseImpl.transferHeaders(response);
909 
910         if (stringResponse.isCalledGetOutputStream()) {
911             UnsyncByteArrayOutputStream ubaos =
912                 stringResponse.getUnsyncByteArrayOutputStream();
913 
914             InputStream is = new UnsyncByteArrayInputStream(
915                 ubaos.unsafeGetByteArray(), 0, ubaos.size());
916 
917             ServletResponseUtil.sendFile(
918                 request, response, renderResponseImpl.getResourceName(), is,
919                 renderResponseImpl.getContentType());
920         }
921         else {
922             byte[] content = stringResponse.getString().getBytes(
923                 StringPool.UTF8);
924 
925             ServletResponseUtil.sendFile(
926                 request, response, renderResponseImpl.getResourceName(),
927                 content, renderResponseImpl.getContentType());
928         }
929 
930         renderRequestImpl.cleanUp();
931     }
932 
933     protected Event serializeEvent(
934         Event event, ClassLoader portletClassLoader) {
935 
936         Serializable value = event.getValue();
937 
938         if (value == null) {
939             return event;
940         }
941 
942         ClassLoader eventClassLoader = value.getClass().getClassLoader();
943 
944         if (portletClassLoader == eventClassLoader) {
945             return event;
946         }
947 
948         EventImpl eventImpl = (EventImpl)event;
949 
950         String base64Value = eventImpl.getBase64Value();
951 
952         value = (Serializable)Base64.stringToObject(
953             base64Value, portletClassLoader);
954 
955         return new EventImpl(event.getName(), event.getQName(), value);
956     }
957 
958     private static Log _log = LogFactoryUtil.getLog(LayoutAction.class);
959 
960 }