001    /**
002     * Copyright (c) 2000-present 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.PortletBag;
018    import com.liferay.portal.kernel.portlet.PortletBagPool;
019    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
020    import com.liferay.portal.kernel.util.ClassLoaderUtil;
021    import com.liferay.portal.model.Portlet;
022    import com.liferay.portal.model.PortletApp;
023    import com.liferay.portal.model.PortletConstants;
024    import com.liferay.portal.service.PortletLocalServiceUtil;
025    
026    import java.util.Map;
027    import java.util.concurrent.ConcurrentHashMap;
028    
029    import javax.portlet.PortletConfig;
030    import javax.portlet.PortletContext;
031    import javax.portlet.PortletException;
032    
033    import javax.servlet.ServletContext;
034    
035    /**
036     * @author Brian Wing Shun Chan
037     * @author Shuyang Zhou
038     */
039    @DoPrivileged
040    public class PortletInstanceFactoryImpl implements PortletInstanceFactory {
041    
042            public PortletInstanceFactoryImpl() {
043                    _pool = new ConcurrentHashMap<>();
044            }
045    
046            @Override
047            public void clear(Portlet portlet) {
048                    clear(portlet, true);
049            }
050    
051            @Override
052            public void clear(Portlet portlet, boolean resetRemotePortletBag) {
053                    String rootPortletId = portlet.getRootPortletId();
054    
055                    Map<String, InvokerPortlet> portletInstances = _pool.remove(
056                            rootPortletId);
057    
058                    if (portletInstances != null) {
059                            InvokerPortlet rootInvokerPortletInstance = portletInstances.remove(
060                                    rootPortletId);
061    
062                            if (rootInvokerPortletInstance != null) {
063                                    rootInvokerPortletInstance.destroy();
064                            }
065    
066                            portletInstances.clear();
067                    }
068    
069                    PortletApp portletApp = portlet.getPortletApp();
070    
071                    if (resetRemotePortletBag && portletApp.isWARFile()) {
072                            PortletBag portletBag = PortletBagPool.remove(rootPortletId);
073    
074                            if (portletBag != null) {
075                                    portletBag.destroy();
076                            }
077                    }
078            }
079    
080            @Override
081            public InvokerPortlet create(Portlet portlet, ServletContext servletContext)
082                    throws PortletException {
083    
084                    boolean instanceable = false;
085    
086                    boolean deployed = !portlet.isUndeployedPortlet();
087    
088                    if (portlet.isInstanceable() && deployed &&
089                            PortletConstants.hasInstanceId(portlet.getPortletId())) {
090    
091                            instanceable = true;
092                    }
093    
094                    String rootPortletId = portlet.getRootPortletId();
095    
096                    InvokerPortlet rootInvokerPortletInstance = null;
097    
098                    Map<String, InvokerPortlet> portletInstances = null;
099    
100                    if (deployed) {
101                            portletInstances = _pool.get(rootPortletId);
102    
103                            if (portletInstances == null) {
104                                    portletInstances = new ConcurrentHashMap<>();
105    
106                                    _pool.put(rootPortletId, portletInstances);
107                            }
108                            else {
109                                    if (instanceable) {
110                                            InvokerPortlet instanceInvokerPortletInstance =
111                                                    portletInstances.get(portlet.getPortletId());
112    
113                                            if (instanceInvokerPortletInstance != null) {
114                                                    return instanceInvokerPortletInstance;
115                                            }
116                                    }
117    
118                                    rootInvokerPortletInstance = portletInstances.get(
119                                            rootPortletId);
120                            }
121                    }
122    
123                    if (rootInvokerPortletInstance == null) {
124                            PortletBag portletBag = PortletBagPool.get(rootPortletId);
125    
126                            // Portlet bag should never be null unless the portlet has been
127                            // undeployed
128    
129                            if (portletBag == null) {
130                                    PortletBagFactory portletBagFactory = new PortletBagFactory();
131    
132                                    portletBagFactory.setClassLoader(
133                                            ClassLoaderUtil.getPortalClassLoader());
134                                    portletBagFactory.setServletContext(servletContext);
135                                    portletBagFactory.setWARFile(false);
136    
137                                    try {
138                                            portletBag = portletBagFactory.create(portlet);
139                                    }
140                                    catch (Exception e) {
141                                            throw new PortletException(e);
142                                    }
143                            }
144    
145                            PortletConfig portletConfig = PortletConfigFactoryUtil.create(
146                                    portlet, servletContext);
147    
148                            rootInvokerPortletInstance = init(
149                                    portlet, portletConfig, portletBag.getPortletInstance());
150    
151                            if (deployed) {
152                                    portletInstances.put(rootPortletId, rootInvokerPortletInstance);
153                            }
154                    }
155    
156                    if (!instanceable) {
157                            return rootInvokerPortletInstance;
158                    }
159    
160                    javax.portlet.Portlet portletInstance =
161                            rootInvokerPortletInstance.getPortletInstance();
162    
163                    PortletConfig portletConfig = PortletConfigFactoryUtil.create(
164                            portlet, servletContext);
165    
166                    PortletContext portletContext = portletConfig.getPortletContext();
167                    boolean checkAuthToken = rootInvokerPortletInstance.isCheckAuthToken();
168                    boolean facesPortlet = rootInvokerPortletInstance.isFacesPortlet();
169                    boolean strutsPortlet = rootInvokerPortletInstance.isStrutsPortlet();
170                    boolean strutsBridgePortlet =
171                            rootInvokerPortletInstance.isStrutsBridgePortlet();
172    
173                    InvokerPortlet instanceInvokerPortletInstance =
174                            _invokerPortletFactory.create(
175                                    portlet, portletInstance, portletConfig, portletContext,
176                                    (InvokerFilterContainer)rootInvokerPortletInstance,
177                                    checkAuthToken, facesPortlet, strutsPortlet,
178                                    strutsBridgePortlet);
179    
180                    if (deployed) {
181                            portletInstances.put(
182                                    portlet.getPortletId(), instanceInvokerPortletInstance);
183                    }
184    
185                    return instanceInvokerPortletInstance;
186            }
187    
188            @Override
189            public void delete(Portlet portlet) {
190                    if (PortletConstants.hasInstanceId(portlet.getPortletId())) {
191                            Map<String, InvokerPortlet> portletInstances = _pool.get(
192                                    portlet.getRootPortletId());
193    
194                            if (portletInstances != null) {
195                                    portletInstances.remove(portlet.getPortletId());
196                            }
197                    }
198            }
199    
200            public void destroy() {
201    
202                    // LPS-10473
203    
204            }
205    
206            @Override
207            public void destroy(Portlet portlet) {
208                    clear(portlet);
209    
210                    PortletConfigFactoryUtil.destroy(portlet);
211                    PortletContextFactory.destroy(portlet);
212    
213                    PortletLocalServiceUtil.destroyPortlet(portlet);
214            }
215    
216            public void setInvokerPortletFactory(
217                    InvokerPortletFactory invokerPortletFactory) {
218    
219                    _invokerPortletFactory = invokerPortletFactory;
220            }
221    
222            protected InvokerPortlet init(
223                            Portlet portlet, PortletConfig portletConfig,
224                            javax.portlet.Portlet portletInstance)
225                    throws PortletException {
226    
227                    PortletContext portletContext = portletConfig.getPortletContext();
228    
229                    InvokerFilterContainer invokerFilterContainer =
230                            new InvokerFilterContainerImpl(portlet, portletContext);
231    
232                    InvokerPortlet invokerPortlet = _invokerPortletFactory.create(
233                            portlet, portletInstance, portletContext, invokerFilterContainer);
234    
235                    invokerPortlet.init(portletConfig);
236    
237                    return invokerPortlet;
238            }
239    
240            private InvokerPortletFactory _invokerPortletFactory;
241            private final Map<String, Map<String, InvokerPortlet>> _pool;
242    
243    }