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