001    /**
002     * Copyright (c) 2000-2012 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.portlet;
016    
017    import com.liferay.portal.kernel.portlet.ActionResult;
018    import com.liferay.portal.kernel.portlet.PortletContainer;
019    import com.liferay.portal.kernel.portlet.PortletContainerException;
020    import com.liferay.portal.kernel.portlet.RestrictPortletServletRequest;
021    import com.liferay.portal.kernel.util.ServerDetector;
022    import com.liferay.portal.kernel.util.WebKeys;
023    import com.liferay.portal.model.Layout;
024    import com.liferay.portal.model.Portlet;
025    import com.liferay.portal.util.PropsValues;
026    
027    import java.util.List;
028    import java.util.Map;
029    
030    import javax.portlet.Event;
031    
032    import javax.servlet.http.HttpServletRequest;
033    import javax.servlet.http.HttpServletResponse;
034    
035    /**
036     * @author Shuyang Zhou
037     */
038    public class RestrictPortletContainerWrapper implements PortletContainer {
039    
040            public static PortletContainer createRestrictPortletContainerWrapper(
041                    PortletContainer portletContainer) {
042    
043                    if ((PropsValues.LAYOUT_PARALLEL_RENDER_ENABLE &&
044                                    ServerDetector.isTomcat()) ||
045                            PropsValues.PORTLET_CONTAINER_RESTRICT) {
046    
047                            portletContainer = new RestrictPortletContainerWrapper(
048                                    portletContainer);
049                    }
050    
051                    return portletContainer;
052            }
053    
054            public RestrictPortletContainerWrapper(PortletContainer portletContainer) {
055                    _portletContainer = portletContainer;
056            }
057    
058            public void preparePortlet(HttpServletRequest request, Portlet portlet)
059                    throws PortletContainerException {
060    
061                    _portletContainer.preparePortlet(request, portlet);
062            }
063    
064            public ActionResult processAction(
065                            HttpServletRequest request, HttpServletResponse response,
066                            Portlet portlet)
067                    throws PortletContainerException {
068    
069                    RestrictPortletServletRequest restrictPortletServletRequest =
070                            new RestrictPortletServletRequest(request);
071    
072                    try {
073                            return _portletContainer.processAction(request, response, portlet);
074                    }
075                    finally {
076                            restrictPortletServletRequest.mergeSharedAttributes();
077                    }
078            }
079    
080            public List<Event> processEvent(
081                            HttpServletRequest request, HttpServletResponse response,
082                            Portlet portlet, Layout layout, Event event)
083                    throws PortletContainerException {
084    
085                    RestrictPortletServletRequest restrictPortletServletRequest =
086                            new RestrictPortletServletRequest(request);
087    
088                    try {
089                            return _portletContainer.processEvent(
090                                    request, response, portlet, layout, event);
091                    }
092                    finally {
093                            restrictPortletServletRequest.mergeSharedAttributes();
094                    }
095            }
096    
097            public void render(
098                            HttpServletRequest request, HttpServletResponse response,
099                            Portlet portlet)
100                    throws PortletContainerException {
101    
102                    RestrictPortletServletRequest restrictPortletServletRequest = null;
103    
104                    if (request instanceof RestrictPortletServletRequest) {
105                            restrictPortletServletRequest =
106                                    (RestrictPortletServletRequest)request;
107    
108                            Map<String, Object> attributes =
109                                    restrictPortletServletRequest.getAttributes();
110    
111                            if (attributes.containsKey(WebKeys.RENDER_PORTLET)) {
112                                    restrictPortletServletRequest =
113                                            new RestrictPortletServletRequest(request);
114                            }
115                    }
116                    else {
117                            restrictPortletServletRequest =
118                                    new RestrictPortletServletRequest(request);
119                    }
120    
121                    try {
122                            _portletContainer.render(request, response, portlet);
123                    }
124                    catch (Exception e) {
125                            throw new PortletContainerException(e);
126                    }
127                    finally {
128                            restrictPortletServletRequest.removeAttribute(WebKeys.RENDER_PATH);
129                            restrictPortletServletRequest.removeAttribute(
130                                    WebKeys.RENDER_PORTLET_COLUMN_COUNT);
131                            restrictPortletServletRequest.removeAttribute(
132                                    WebKeys.RENDER_PORTLET_COLUMN_ID);
133                            restrictPortletServletRequest.removeAttribute(
134                                    WebKeys.RENDER_PORTLET_COLUMN_POS);
135    
136                            // Don't merge when parallel rendering a portlet. The caller (worker
137                            // thread) should decide whether or not to merge shared attributes.
138                            // If we did merge here and the caller cancelled the parallel
139                            // rendering, then we would have corrupted the set of shared
140                            // attributes. The only safe way to merge shared attributes is for
141                            // the caller to merge after it has the render result.
142    
143                            Object lock = request.getAttribute(
144                                    WebKeys.PARALLEL_RENDERING_MERGE_LOCK);
145    
146                            if (lock == null) {
147                                    restrictPortletServletRequest.mergeSharedAttributes();
148                            }
149                    }
150            }
151    
152            public void serveResource(
153                            HttpServletRequest request, HttpServletResponse response,
154                            Portlet portlet)
155                    throws PortletContainerException {
156    
157                    RestrictPortletServletRequest restrictPortletServletRequest =
158                            new RestrictPortletServletRequest(request);
159    
160                    try {
161                            _portletContainer.serveResource(request, response, portlet);
162                    }
163                    catch (Exception e) {
164                            throw new PortletContainerException(e);
165                    }
166                    finally {
167                            restrictPortletServletRequest.mergeSharedAttributes();
168                    }
169            }
170    
171            private PortletContainer _portletContainer;
172    
173    }