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