001    /**
002     * Copyright (c) 2000-2013 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.resiliency.mpi.portlet;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.portlet.ActionResult;
020    import com.liferay.portal.kernel.portlet.PortletContainer;
021    import com.liferay.portal.kernel.portlet.PortletContainerException;
022    import com.liferay.portal.kernel.resiliency.PortalResiliencyException;
023    import com.liferay.portal.kernel.resiliency.spi.SPI;
024    import com.liferay.portal.kernel.resiliency.spi.SPIRegistryUtil;
025    import com.liferay.portal.kernel.resiliency.spi.agent.SPIAgent;
026    import com.liferay.portal.kernel.util.WebKeys;
027    import com.liferay.portal.model.Layout;
028    import com.liferay.portal.model.Portlet;
029    import com.liferay.portal.util.PropsValues;
030    
031    import java.util.Collections;
032    import java.util.List;
033    
034    import javax.portlet.Event;
035    
036    import javax.servlet.http.HttpServletRequest;
037    import javax.servlet.http.HttpServletResponse;
038    
039    /**
040     * @author Shuyang Zhou
041     */
042    public class PortalResiliencyPortletContainerWrapper
043            implements PortletContainer {
044    
045            public static PortletContainer
046                    createPortalResiliencyPortletContainerWrapper(
047                            PortletContainer portletContainer) {
048    
049                    if (PropsValues.PORTAL_RESILIENCY_ENABLED) {
050                            portletContainer = new PortalResiliencyPortletContainerWrapper(
051                                    portletContainer);
052                    }
053    
054                    return portletContainer;
055            }
056    
057            public PortalResiliencyPortletContainerWrapper(
058                    PortletContainer portletContainer) {
059    
060                    _portletContainer = portletContainer;
061            }
062    
063            @Override
064            public void preparePortlet(HttpServletRequest request, Portlet portlet)
065                    throws PortletContainerException {
066    
067                    _portletContainer.preparePortlet(request, portlet);
068            }
069    
070            @Override
071            public ActionResult processAction(
072                            HttpServletRequest request, HttpServletResponse response,
073                            Portlet portlet)
074                    throws PortletContainerException {
075    
076                    SPIAgent spiAgent = getSPIAgentForPortlet(portlet);
077    
078                    if (spiAgent == null) {
079                            return _portletContainer.processAction(request, response, portlet);
080                    }
081    
082                    Object[] requestAttributeValues = captureRequestAttibutes(
083                            request, _ACTION_REQUEST_ATTRIBUTE_NAMES);
084    
085                    request.setAttribute(
086                            WebKeys.SPI_AGENT_LIFECYCLE, SPIAgent.Lifecycle.ACTION);
087                    request.setAttribute(WebKeys.SPI_AGENT_PORTLET, portlet);
088    
089                    try {
090                            spiAgent.service(request, response);
091    
092                            return (ActionResult)request.getAttribute(
093                                    WebKeys.SPI_AGENT_ACTION_RESULT);
094                    }
095                    catch (PortalResiliencyException pre) {
096                            _log.error(pre, pre);
097    
098                            return ActionResult.EMPTY_ACTION_RESULT;
099                    }
100                    finally {
101                            request.removeAttribute(WebKeys.SPI_AGENT_ACTION_RESULT);
102    
103                            restoreRequestAttibutes(
104                                    request, _ACTION_REQUEST_ATTRIBUTE_NAMES,
105                                    requestAttributeValues);
106                    }
107            }
108    
109            @Override
110            public List<Event> processEvent(
111                            HttpServletRequest request, HttpServletResponse response,
112                            Portlet portlet, Layout layout, Event event)
113                    throws PortletContainerException {
114    
115                    SPIAgent spiAgent = getSPIAgentForPortlet(portlet);
116    
117                    if (spiAgent == null) {
118                            return _portletContainer.processEvent(
119                                    request, response, portlet, layout, event);
120                    }
121    
122                    Object[] requestAttributeValues = captureRequestAttibutes(
123                            request, _EVENT_REQUEST_ATTRIBUTE_NAMES);
124    
125                    request.setAttribute(WebKeys.SPI_AGENT_EVENT, event);
126                    request.setAttribute(WebKeys.SPI_AGENT_LAYOUT, layout);
127                    request.setAttribute(
128                            WebKeys.SPI_AGENT_LIFECYCLE, SPIAgent.Lifecycle.EVENT);
129                    request.setAttribute(WebKeys.SPI_AGENT_PORTLET, portlet);
130    
131                    try {
132                            spiAgent.service(request, response);
133    
134                            return (List<Event>)request.getAttribute(
135                                    WebKeys.SPI_AGENT_EVENT_RESULT);
136                    }
137                    catch (PortalResiliencyException pre) {
138                            _log.error(pre, pre);
139    
140                            return Collections.emptyList();
141                    }
142                    finally {
143                            request.removeAttribute(WebKeys.SPI_AGENT_EVENT_RESULT);
144    
145                            restoreRequestAttibutes(
146                                    request, _EVENT_REQUEST_ATTRIBUTE_NAMES,
147                                    requestAttributeValues);
148                    }
149            }
150    
151            @Override
152            public void render(
153                            HttpServletRequest request, HttpServletResponse response,
154                            Portlet portlet)
155                    throws PortletContainerException {
156    
157                    SPIAgent spiAgent = getSPIAgentForPortlet(portlet);
158    
159                    if (spiAgent == null) {
160                            _portletContainer.render(request, response, portlet);
161    
162                            return;
163                    }
164    
165                    Object[] requestAttributeValues = captureRequestAttibutes(
166                            request, _RENDER_REQUEST_ATTRIBUTE_NAMES);
167    
168                    request.setAttribute(
169                            WebKeys.SPI_AGENT_LIFECYCLE, SPIAgent.Lifecycle.RENDER);
170                    request.setAttribute(WebKeys.SPI_AGENT_PORTLET, portlet);
171    
172                    try {
173                            spiAgent.service(request, response);
174                    }
175                    catch (PortalResiliencyException pre) {
176                            _log.error(pre, pre);
177                    }
178                    finally {
179                            restoreRequestAttibutes(
180                                    request, _RENDER_REQUEST_ATTRIBUTE_NAMES,
181                                    requestAttributeValues);
182                    }
183            }
184    
185            @Override
186            public void serveResource(
187                            HttpServletRequest request, HttpServletResponse response,
188                            Portlet portlet)
189                    throws PortletContainerException {
190    
191                    SPIAgent spiAgent = getSPIAgentForPortlet(portlet);
192    
193                    if (spiAgent == null) {
194                            _portletContainer.serveResource(request, response, portlet);
195    
196                            return;
197                    }
198    
199                    Object[] requestAttributeValues = captureRequestAttibutes(
200                            request, _RESOURCE_REQUEST_ATTRIBUTE_NAMES);
201    
202                    request.setAttribute(
203                            WebKeys.SPI_AGENT_LIFECYCLE, SPIAgent.Lifecycle.RESOURCE);
204                    request.setAttribute(WebKeys.SPI_AGENT_PORTLET, portlet);
205    
206                    try {
207                            spiAgent.service(request, response);
208                    }
209                    catch (PortalResiliencyException pre) {
210                            _log.error(pre, pre);
211                    }
212                    finally {
213                            restoreRequestAttibutes(
214                                    request, _RESOURCE_REQUEST_ATTRIBUTE_NAMES,
215                                    requestAttributeValues);
216                    }
217            }
218    
219            protected Object[] captureRequestAttibutes(
220                    HttpServletRequest request, String... names) {
221    
222                    Object[] values = new Object[names.length];
223    
224                    for (int i = 0; i < names.length; i++) {
225                            values[i] = request.getAttribute(names[i]);
226                    }
227    
228                    return values;
229            }
230    
231            protected SPIAgent getSPIAgentForPortlet(Portlet portlet)
232                    throws PortletContainerException {
233    
234                    try {
235                            SPI spi = SPIRegistryUtil.getPortletSPI(portlet.getRootPortletId());
236    
237                            if (spi == null) {
238                                    return null;
239                            }
240    
241                            if (_log.isDebugEnabled()) {
242                                    _log.debug(
243                                            "Portlet " + portlet + " is registered to SPI " + spi);
244                            }
245    
246                            return spi.getSPIAgent();
247                    }
248                    catch (Exception e) {
249                            throw new PortletContainerException(e);
250                    }
251            }
252    
253            protected void restoreRequestAttibutes(
254                    HttpServletRequest request, String[] names, Object[] values) {
255    
256                    for (int i = 0; i < names.length; i++) {
257                            String name = names[i];
258                            Object value = values[i];
259    
260                            if (value == null) {
261                                    request.removeAttribute(name);
262                            }
263                            else {
264                                    request.setAttribute(name, value);
265                            }
266                    }
267            }
268    
269            private static final String[] _ACTION_REQUEST_ATTRIBUTE_NAMES =
270                    {WebKeys.SPI_AGENT_LIFECYCLE, WebKeys.SPI_AGENT_PORTLET};
271    
272            private static final String[] _EVENT_REQUEST_ATTRIBUTE_NAMES =
273                    {WebKeys.SPI_AGENT_EVENT, WebKeys.SPI_AGENT_LAYOUT,
274                            WebKeys.SPI_AGENT_LIFECYCLE, WebKeys.SPI_AGENT_PORTLET};
275    
276            private static final String[] _RENDER_REQUEST_ATTRIBUTE_NAMES =
277                    _ACTION_REQUEST_ATTRIBUTE_NAMES;
278    
279            private static final String[] _RESOURCE_REQUEST_ATTRIBUTE_NAMES =
280                    _ACTION_REQUEST_ATTRIBUTE_NAMES;
281    
282            private static Log _log = LogFactoryUtil.getLog(
283                    PortalResiliencyPortletContainerWrapper.class);
284    
285            private PortletContainer _portletContainer;
286    
287    }