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                    boolean instanceable = false;
103    
104                    boolean deployed = !portlet.isUndeployedPortlet();
105    
106                    if (portlet.isInstanceable() && deployed &&
107                            PortletConstants.hasInstanceId(portlet.getPortletId())) {
108    
109                            instanceable = true;
110                    }
111    
112                    String rootPortletId = portlet.getRootPortletId();
113    
114                    InvokerPortlet rootInvokerPortletInstance = null;
115    
116                    Map<String, InvokerPortlet> portletInstances = null;
117    
118                    if (deployed) {
119                            portletInstances = _pool.get(rootPortletId);
120    
121                            if (portletInstances == null) {
122                                    portletInstances = new ConcurrentHashMap<>();
123    
124                                    _pool.put(rootPortletId, portletInstances);
125                            }
126                            else {
127                                    if (instanceable) {
128                                            InvokerPortlet instanceInvokerPortletInstance =
129                                                    portletInstances.get(portlet.getPortletId());
130    
131                                            if (instanceInvokerPortletInstance != null) {
132                                                    return instanceInvokerPortletInstance;
133                                            }
134                                    }
135    
136                                    rootInvokerPortletInstance = portletInstances.get(
137                                            rootPortletId);
138                            }
139                    }
140    
141                    if (rootInvokerPortletInstance == null) {
142                            PortletBag portletBag = PortletBagPool.get(rootPortletId);
143    
144                            // Portlet bag should never be null unless the portlet has been
145                            // undeployed
146    
147                            if (portletBag == null) {
148                                    PortletBagFactory portletBagFactory = new PortletBagFactory();
149    
150                                    portletBagFactory.setClassLoader(
151                                            ClassLoaderUtil.getPortalClassLoader());
152                                    portletBagFactory.setServletContext(servletContext);
153                                    portletBagFactory.setWARFile(false);
154    
155                                    try {
156                                            portletBag = portletBagFactory.create(portlet);
157                                    }
158                                    catch (Exception e) {
159                                            throw new PortletException(e);
160                                    }
161                            }
162    
163                            PortletConfig portletConfig = PortletConfigFactoryUtil.create(
164                                    portlet, servletContext);
165    
166                            rootInvokerPortletInstance = init(
167                                    portlet, portletConfig, portletBag.getPortletInstance());
168    
169                            if (deployed) {
170                                    portletInstances.put(rootPortletId, rootInvokerPortletInstance);
171                            }
172                    }
173    
174                    if (!instanceable) {
175                            return rootInvokerPortletInstance;
176                    }
177    
178                    javax.portlet.Portlet portletInstance =
179                            rootInvokerPortletInstance.getPortletInstance();
180    
181                    PortletConfig portletConfig = PortletConfigFactoryUtil.create(
182                            portlet, servletContext);
183    
184                    PortletContext portletContext = portletConfig.getPortletContext();
185                    boolean checkAuthToken = rootInvokerPortletInstance.isCheckAuthToken();
186                    boolean facesPortlet = rootInvokerPortletInstance.isFacesPortlet();
187                    boolean strutsPortlet = rootInvokerPortletInstance.isStrutsPortlet();
188                    boolean strutsBridgePortlet =
189                            rootInvokerPortletInstance.isStrutsBridgePortlet();
190    
191                    InvokerPortlet instanceInvokerPortletInstance =
192                            _invokerPortletFactory.create(
193                                    portlet, portletInstance, portletConfig, portletContext,
194                                    (InvokerFilterContainer)rootInvokerPortletInstance,
195                                    checkAuthToken, facesPortlet, strutsPortlet,
196                                    strutsBridgePortlet);
197    
198                    if (deployed) {
199                            portletInstances.put(
200                                    portlet.getPortletId(), instanceInvokerPortletInstance);
201                    }
202    
203                    return instanceInvokerPortletInstance;
204            }
205    
206            @Override
207            public void delete(Portlet portlet) {
208                    if (PortletConstants.hasInstanceId(portlet.getPortletId())) {
209                            Map<String, InvokerPortlet> portletInstances = _pool.get(
210                                    portlet.getRootPortletId());
211    
212                            if (portletInstances != null) {
213                                    portletInstances.remove(portlet.getPortletId());
214                            }
215                    }
216            }
217    
218            public void destroy() {
219    
220                    // LPS-10473
221    
222            }
223    
224            @Override
225            public void destroy(Portlet portlet) {
226                    _serviceTracker.close();
227    
228                    clear(portlet);
229    
230                    PortletConfigFactoryUtil.destroy(portlet);
231                    PortletContextFactory.destroy(portlet);
232    
233                    PortletLocalServiceUtil.destroyPortlet(portlet);
234            }
235    
236            protected InvokerPortlet init(
237                            Portlet portlet, PortletConfig portletConfig,
238                            javax.portlet.Portlet portletInstance)
239                    throws PortletException {
240    
241                    PortletContext portletContext = portletConfig.getPortletContext();
242    
243                    InvokerFilterContainer invokerFilterContainer =
244                            new InvokerFilterContainerImpl(portlet, portletContext);
245    
246                    InvokerPortlet invokerPortlet = _invokerPortletFactory.create(
247                            portlet, portletInstance, portletContext, invokerFilterContainer);
248    
249                    invokerPortlet.init(portletConfig);
250    
251                    return invokerPortlet;
252            }
253    
254            private InvokerPortletFactory _invokerPortletFactory;
255            private final Map<String, Map<String, InvokerPortlet>> _pool;
256            private final ServiceTracker<InvokerPortletFactory, InvokerPortletFactory>
257                    _serviceTracker;
258    
259            private class InvokerPortletFactoryTrackerCustomizer
260                    implements ServiceTrackerCustomizer
261                            <InvokerPortletFactory, InvokerPortletFactory> {
262    
263                    @Override
264                    public InvokerPortletFactory addingService(
265                            ServiceReference<InvokerPortletFactory> serviceReference) {
266    
267                            Registry registry = RegistryUtil.getRegistry();
268    
269                            InvokerPortletFactory invokerPortletFactory = registry.getService(
270                                    serviceReference);
271    
272                            _invokerPortletFactory = invokerPortletFactory;
273    
274                            return invokerPortletFactory;
275                    }
276    
277                    @Override
278                    public void modifiedService(
279                            ServiceReference<InvokerPortletFactory> serviceReference,
280                            InvokerPortletFactory invokerPortletFactory) {
281                    }
282    
283                    @Override
284                    public void removedService(
285                            ServiceReference<InvokerPortletFactory> serviceReference,
286                            InvokerPortletFactory invokerPortletFactory) {
287    
288                            Registry registry = RegistryUtil.getRegistry();
289    
290                            registry.ungetService(serviceReference);
291                    }
292    
293            }
294    
295    }