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    import com.liferay.portal.util.PortletKeys;
026    import com.liferay.registry.Filter;
027    import com.liferay.registry.Registry;
028    import com.liferay.registry.RegistryUtil;
029    import com.liferay.registry.ServiceReference;
030    import com.liferay.registry.ServiceTracker;
031    import com.liferay.registry.ServiceTrackerCustomizer;
032    
033    import java.util.Map;
034    import java.util.concurrent.ConcurrentHashMap;
035    
036    import javax.portlet.PortletConfig;
037    import javax.portlet.PortletContext;
038    import javax.portlet.PortletException;
039    
040    import javax.servlet.ServletContext;
041    
042    /**
043     * @author Brian Wing Shun Chan
044     * @author Shuyang Zhou
045     */
046    @DoPrivileged
047    public class PortletInstanceFactoryImpl implements PortletInstanceFactory {
048    
049            public PortletInstanceFactoryImpl() {
050                    _pool = new ConcurrentHashMap<>();
051    
052                    Registry registry = RegistryUtil.getRegistry();
053    
054                    Filter filter = registry.getFilter(
055                            "(&(javax.portlet.name=" + PortletKeys.MONITORING_INVOKER + ")" +
056                                    "(objectClass=" + InvokerPortletFactory.class.getName() + "))");
057    
058                    _serviceTracker = registry.trackServices(
059                            filter, new InvokerPortletFactoryTrackerCustomizer());
060    
061                    _serviceTracker.open();
062            }
063    
064            @Override
065            public void clear(Portlet portlet) {
066                    clear(portlet, true);
067            }
068    
069            @Override
070            public void clear(Portlet portlet, boolean resetRemotePortletBag) {
071                    String rootPortletId = portlet.getRootPortletId();
072    
073                    Map<String, InvokerPortlet> portletInstances = _pool.remove(
074                            rootPortletId);
075    
076                    if (portletInstances != null) {
077                            InvokerPortlet rootInvokerPortletInstance = portletInstances.remove(
078                                    rootPortletId);
079    
080                            if (rootInvokerPortletInstance != null) {
081                                    rootInvokerPortletInstance.destroy();
082                            }
083    
084                            portletInstances.clear();
085                    }
086    
087                    PortletApp portletApp = portlet.getPortletApp();
088    
089                    if (resetRemotePortletBag && portletApp.isWARFile()) {
090                            PortletBag portletBag = PortletBagPool.remove(rootPortletId);
091    
092                            if (portletBag != null) {
093                                    portletBag.destroy();
094                            }
095                    }
096            }
097    
098            @Override
099            public InvokerPortlet create(Portlet portlet, ServletContext servletContext)
100                    throws PortletException {
101    
102                    return create (portlet, servletContext, false);
103            }
104    
105            @Override
106            public InvokerPortlet create(
107                            Portlet portlet, ServletContext servletContext,
108                            boolean destroyPrevious)
109                    throws PortletException {
110    
111                    if (destroyPrevious) {
112                            destroyRelated(portlet);
113                    }
114    
115                    boolean instanceable = false;
116    
117                    boolean deployed = !portlet.isUndeployedPortlet();
118    
119                    if (portlet.isInstanceable() && deployed &&
120                            PortletConstants.hasInstanceId(portlet.getPortletId())) {
121    
122                            instanceable = true;
123                    }
124    
125                    String rootPortletId = portlet.getRootPortletId();
126    
127                    InvokerPortlet rootInvokerPortletInstance = null;
128    
129                    Map<String, InvokerPortlet> portletInstances = null;
130    
131                    if (deployed) {
132                            portletInstances = _pool.get(rootPortletId);
133    
134                            if (portletInstances == null) {
135                                    portletInstances = new ConcurrentHashMap<>();
136    
137                                    _pool.put(rootPortletId, portletInstances);
138                            }
139                            else {
140                                    if (instanceable) {
141                                            InvokerPortlet instanceInvokerPortletInstance =
142                                                    portletInstances.get(portlet.getPortletId());
143    
144                                            if (instanceInvokerPortletInstance != null) {
145                                                    return instanceInvokerPortletInstance;
146                                            }
147                                    }
148    
149                                    rootInvokerPortletInstance = portletInstances.get(
150                                            rootPortletId);
151                            }
152                    }
153    
154                    if (rootInvokerPortletInstance == null) {
155                            PortletBag portletBag = PortletBagPool.get(rootPortletId);
156    
157                            // Portlet bag should never be null unless the portlet has been
158                            // undeployed
159    
160                            if (portletBag == null) {
161                                    PortletBagFactory portletBagFactory = new PortletBagFactory();
162    
163                                    portletBagFactory.setClassLoader(
164                                            ClassLoaderUtil.getPortalClassLoader());
165                                    portletBagFactory.setServletContext(servletContext);
166                                    portletBagFactory.setWARFile(false);
167    
168                                    try {
169                                            portletBag = portletBagFactory.create(portlet);
170                                    }
171                                    catch (Exception e) {
172                                            throw new PortletException(e);
173                                    }
174                            }
175    
176                            PortletConfig portletConfig = PortletConfigFactoryUtil.create(
177                                    portlet, servletContext);
178    
179                            rootInvokerPortletInstance = init(
180                                    portlet, portletConfig, portletBag.getPortletInstance());
181    
182                            if (deployed) {
183                                    portletInstances.put(rootPortletId, rootInvokerPortletInstance);
184                            }
185                    }
186    
187                    if (!instanceable) {
188                            return rootInvokerPortletInstance;
189                    }
190    
191                    javax.portlet.Portlet portletInstance =
192                            rootInvokerPortletInstance.getPortletInstance();
193    
194                    PortletConfig portletConfig = PortletConfigFactoryUtil.create(
195                            portlet, servletContext);
196    
197                    PortletContext portletContext = portletConfig.getPortletContext();
198                    boolean checkAuthToken = rootInvokerPortletInstance.isCheckAuthToken();
199                    boolean facesPortlet = rootInvokerPortletInstance.isFacesPortlet();
200                    boolean strutsPortlet = rootInvokerPortletInstance.isStrutsPortlet();
201                    boolean strutsBridgePortlet =
202                            rootInvokerPortletInstance.isStrutsBridgePortlet();
203    
204                    InvokerPortlet instanceInvokerPortletInstance =
205                            _invokerPortletFactory.create(
206                                    portlet, portletInstance, portletConfig, portletContext,
207                                    (InvokerFilterContainer)rootInvokerPortletInstance,
208                                    checkAuthToken, facesPortlet, strutsPortlet,
209                                    strutsBridgePortlet);
210    
211                    if (deployed) {
212                            portletInstances.put(
213                                    portlet.getPortletId(), instanceInvokerPortletInstance);
214                    }
215    
216                    return instanceInvokerPortletInstance;
217            }
218    
219            @Override
220            public void delete(Portlet portlet) {
221                    if (PortletConstants.hasInstanceId(portlet.getPortletId())) {
222                            Map<String, InvokerPortlet> portletInstances = _pool.get(
223                                    portlet.getRootPortletId());
224    
225                            if (portletInstances != null) {
226                                    portletInstances.remove(portlet.getPortletId());
227                            }
228                    }
229            }
230    
231            public void destroy() {
232    
233                    // LPS-10473
234    
235            }
236    
237            @Override
238            public void destroy(Portlet portlet) {
239                    _serviceTracker.close();
240    
241                    clear(portlet);
242    
243                    destroyRelated(portlet);
244    
245                    PortletLocalServiceUtil.destroyPortlet(portlet);
246            }
247    
248            protected void destroyRelated(Portlet portlet) {
249                    PortletConfigFactoryUtil.destroy(portlet);
250                    PortletContextFactoryUtil.destroy(portlet);
251            }
252    
253            protected InvokerPortlet init(
254                            Portlet portlet, PortletConfig portletConfig,
255                            javax.portlet.Portlet portletInstance)
256                    throws PortletException {
257    
258                    PortletContext portletContext = portletConfig.getPortletContext();
259    
260                    InvokerFilterContainer invokerFilterContainer =
261                            new InvokerFilterContainerImpl(portlet, portletContext);
262    
263                    InvokerPortlet invokerPortlet = _invokerPortletFactory.create(
264                            portlet, portletInstance, portletContext, invokerFilterContainer);
265    
266                    invokerPortlet.init(portletConfig);
267    
268                    return invokerPortlet;
269            }
270    
271            private InvokerPortletFactory _invokerPortletFactory;
272            private final Map<String, Map<String, InvokerPortlet>> _pool;
273            private final ServiceTracker<InvokerPortletFactory, InvokerPortletFactory>
274                    _serviceTracker;
275    
276            private class InvokerPortletFactoryTrackerCustomizer
277                    implements ServiceTrackerCustomizer
278                            <InvokerPortletFactory, InvokerPortletFactory> {
279    
280                    @Override
281                    public InvokerPortletFactory addingService(
282                            ServiceReference<InvokerPortletFactory> serviceReference) {
283    
284                            Registry registry = RegistryUtil.getRegistry();
285    
286                            InvokerPortletFactory invokerPortletFactory = registry.getService(
287                                    serviceReference);
288    
289                            _invokerPortletFactory = invokerPortletFactory;
290    
291                            return invokerPortletFactory;
292                    }
293    
294                    @Override
295                    public void modifiedService(
296                            ServiceReference<InvokerPortletFactory> serviceReference,
297                            InvokerPortletFactory invokerPortletFactory) {
298                    }
299    
300                    @Override
301                    public void removedService(
302                            ServiceReference<InvokerPortletFactory> serviceReference,
303                            InvokerPortletFactory invokerPortletFactory) {
304    
305                            Registry registry = RegistryUtil.getRegistry();
306    
307                            registry.ungetService(serviceReference);
308                    }
309    
310            }
311    
312    }