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.model.Portlet;
021    import com.liferay.portal.model.PortletApp;
022    import com.liferay.portal.model.PortletConstants;
023    import com.liferay.portal.service.PortletLocalServiceUtil;
024    import com.liferay.portal.util.ClassLoaderUtil;
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<String, Map<String, InvokerPortlet>>();
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 =
105                                            new ConcurrentHashMap<String, InvokerPortlet>();
106    
107                                    _pool.put(rootPortletId, portletInstances);
108                            }
109                            else {
110                                    if (instanceable) {
111                                            InvokerPortlet instanceInvokerPortletInstance =
112                                                    portletInstances.get(portlet.getPortletId());
113    
114                                            if (instanceInvokerPortletInstance != null) {
115                                                    return instanceInvokerPortletInstance;
116                                            }
117                                    }
118    
119                                    rootInvokerPortletInstance = portletInstances.get(
120                                            rootPortletId);
121                            }
122                    }
123    
124                    if (rootInvokerPortletInstance == null) {
125                            PortletBag portletBag = PortletBagPool.get(rootPortletId);
126    
127                            // Portlet bag should never be null unless the portlet has been
128                            // undeployed
129    
130                            if (portletBag == null) {
131                                    PortletBagFactory portletBagFactory = new PortletBagFactory();
132    
133                                    portletBagFactory.setClassLoader(
134                                            ClassLoaderUtil.getPortalClassLoader());
135                                    portletBagFactory.setServletContext(servletContext);
136                                    portletBagFactory.setWARFile(false);
137    
138                                    try {
139                                            portletBag = portletBagFactory.create(portlet);
140                                    }
141                                    catch (Exception e) {
142                                            throw new PortletException(e);
143                                    }
144                            }
145    
146                            PortletConfig portletConfig = PortletConfigFactoryUtil.create(
147                                    portlet, servletContext);
148    
149                            rootInvokerPortletInstance = init(
150                                    portlet, portletConfig, portletBag.getPortletInstance());
151    
152                            if (deployed) {
153                                    portletInstances.put(rootPortletId, rootInvokerPortletInstance);
154                            }
155                    }
156    
157                    if (!instanceable) {
158                            return rootInvokerPortletInstance;
159                    }
160    
161                    javax.portlet.Portlet portletInstance =
162                            rootInvokerPortletInstance.getPortletInstance();
163    
164                    PortletConfig portletConfig = PortletConfigFactoryUtil.create(
165                            portlet, servletContext);
166    
167                    PortletContext portletContext = portletConfig.getPortletContext();
168                    boolean checkAuthToken = rootInvokerPortletInstance.isCheckAuthToken();
169                    boolean facesPortlet = rootInvokerPortletInstance.isFacesPortlet();
170                    boolean strutsPortlet = rootInvokerPortletInstance.isStrutsPortlet();
171                    boolean strutsBridgePortlet =
172                            rootInvokerPortletInstance.isStrutsBridgePortlet();
173    
174                    InvokerPortlet instanceInvokerPortletInstance =
175                            _invokerPortletFactory.create(
176                                    portlet, portletInstance, portletConfig, portletContext,
177                                    (InvokerFilterContainer)rootInvokerPortletInstance,
178                                    checkAuthToken, facesPortlet, strutsPortlet,
179                                    strutsBridgePortlet);
180    
181                    if (deployed) {
182                            portletInstances.put(
183                                    portlet.getPortletId(), instanceInvokerPortletInstance);
184                    }
185    
186                    return instanceInvokerPortletInstance;
187            }
188    
189            @Override
190            public void delete(Portlet portlet) {
191                    if (PortletConstants.hasInstanceId(portlet.getPortletId())) {
192                            Map<String, InvokerPortlet> portletInstances = _pool.get(
193                                    portlet.getRootPortletId());
194    
195                            if (portletInstances != null) {
196                                    portletInstances.remove(portlet.getPortletId());
197                            }
198                    }
199            }
200    
201            public void destroy() {
202    
203                    // LPS-10473
204    
205            }
206    
207            @Override
208            public void destroy(Portlet portlet) {
209                    clear(portlet);
210    
211                    PortletConfigFactoryUtil.destroy(portlet);
212                    PortletContextFactory.destroy(portlet);
213    
214                    PortletLocalServiceUtil.destroyPortlet(portlet);
215            }
216    
217            public void setInvokerPortletFactory(
218                    InvokerPortletFactory invokerPortletFactory) {
219    
220                    _invokerPortletFactory = invokerPortletFactory;
221            }
222    
223            protected InvokerPortlet init(
224                            Portlet portlet, PortletConfig portletConfig,
225                            javax.portlet.Portlet portletInstance)
226                    throws PortletException {
227    
228                    PortletContext portletContext = portletConfig.getPortletContext();
229    
230                    InvokerFilterContainer invokerFilterContainer =
231                            new InvokerFilterContainerImpl(portlet, portletContext);
232    
233                    InvokerPortlet invokerPortlet = _invokerPortletFactory.create(
234                            portlet, portletInstance, portletContext, invokerFilterContainer);
235    
236                    invokerPortlet.init(portletConfig);
237    
238                    return invokerPortlet;
239            }
240    
241            private InvokerPortletFactory _invokerPortletFactory;
242            private final Map<String, Map<String, InvokerPortlet>> _pool;
243    
244    }