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