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