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.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                            PortletBagPool.remove(rootPortletId);
073                    }
074            }
075    
076            @Override
077            public InvokerPortlet create(Portlet portlet, ServletContext servletContext)
078                    throws PortletException {
079    
080                    boolean instanceable = false;
081    
082                    boolean deployed = !portlet.isUndeployedPortlet();
083    
084                    if (portlet.isInstanceable() && deployed &&
085                            PortletConstants.hasInstanceId(portlet.getPortletId())) {
086    
087                            instanceable = true;
088                    }
089    
090                    String rootPortletId = portlet.getRootPortletId();
091    
092                    InvokerPortlet rootInvokerPortletInstance = null;
093    
094                    Map<String, InvokerPortlet> portletInstances = null;
095    
096                    if (deployed) {
097                            portletInstances = _pool.get(rootPortletId);
098    
099                            if (portletInstances == null) {
100                                    portletInstances =
101                                            new ConcurrentHashMap<String, InvokerPortlet>();
102    
103                                    _pool.put(rootPortletId, portletInstances);
104                            }
105                            else {
106                                    if (instanceable) {
107                                            InvokerPortlet instanceInvokerPortletInstance =
108                                                    portletInstances.get(portlet.getPortletId());
109    
110                                            if (instanceInvokerPortletInstance != null) {
111                                                    return instanceInvokerPortletInstance;
112                                            }
113                                    }
114    
115                                    rootInvokerPortletInstance = portletInstances.get(
116                                            rootPortletId);
117                            }
118                    }
119    
120                    if (rootInvokerPortletInstance == null) {
121                            PortletBag portletBag = PortletBagPool.get(rootPortletId);
122    
123                            // Portlet bag should never be null unless the portlet has been
124                            // undeployed
125    
126                            if (portletBag == null) {
127                                    PortletBagFactory portletBagFactory = new PortletBagFactory();
128    
129                                    portletBagFactory.setClassLoader(
130                                            ClassLoaderUtil.getPortalClassLoader());
131                                    portletBagFactory.setServletContext(servletContext);
132                                    portletBagFactory.setWARFile(false);
133    
134                                    try {
135                                            portletBag = portletBagFactory.create(portlet);
136                                    }
137                                    catch (Exception e) {
138                                            throw new PortletException(e);
139                                    }
140                            }
141    
142                            PortletConfig portletConfig = PortletConfigFactoryUtil.create(
143                                    portlet, servletContext);
144    
145                            rootInvokerPortletInstance = init(
146                                    portlet, portletConfig, portletBag.getPortletInstance());
147    
148                            if (deployed) {
149                                    portletInstances.put(rootPortletId, rootInvokerPortletInstance);
150                            }
151                    }
152    
153                    if (!instanceable) {
154                            return rootInvokerPortletInstance;
155                    }
156    
157                    javax.portlet.Portlet portletInstance =
158                            rootInvokerPortletInstance.getPortletInstance();
159    
160                    PortletConfig portletConfig = PortletConfigFactoryUtil.create(
161                            portlet, servletContext);
162    
163                    PortletContext portletContext = portletConfig.getPortletContext();
164                    boolean checkAuthToken = rootInvokerPortletInstance.isCheckAuthToken();
165                    boolean facesPortlet = rootInvokerPortletInstance.isFacesPortlet();
166                    boolean strutsPortlet = rootInvokerPortletInstance.isStrutsPortlet();
167                    boolean strutsBridgePortlet =
168                            rootInvokerPortletInstance.isStrutsBridgePortlet();
169    
170                    InvokerPortlet instanceInvokerPortletInstance =
171                            _invokerPortletFactory.create(
172                                    portlet, portletInstance, portletConfig, portletContext,
173                                    checkAuthToken, facesPortlet, strutsPortlet,
174                                    strutsBridgePortlet);
175    
176                    if (deployed) {
177                            portletInstances.put(
178                                    portlet.getPortletId(), instanceInvokerPortletInstance);
179                    }
180    
181                    return instanceInvokerPortletInstance;
182            }
183    
184            @Override
185            public void delete(Portlet portlet) {
186                    if (PortletConstants.hasInstanceId(portlet.getPortletId())) {
187                            Map<String, InvokerPortlet> portletInstances = _pool.get(
188                                    portlet.getRootPortletId());
189    
190                            if (portletInstances != null) {
191                                    portletInstances.remove(portlet.getPortletId());
192                            }
193                    }
194            }
195    
196            public void destroy() {
197    
198                    // LPS-10473
199    
200            }
201    
202            @Override
203            public void destroy(Portlet portlet) {
204                    clear(portlet);
205    
206                    PortletConfigFactoryUtil.destroy(portlet);
207                    PortletContextFactory.destroy(portlet);
208    
209                    PortletLocalServiceUtil.destroyPortlet(portlet);
210            }
211    
212            public void setInvokerPortletFactory(
213                    InvokerPortletFactory invokerPortletFactory) {
214    
215                    _invokerPortletFactory = invokerPortletFactory;
216            }
217    
218            protected InvokerPortlet init(
219                            Portlet portlet, PortletConfig portletConfig,
220                            javax.portlet.Portlet portletInstance)
221                    throws PortletException {
222    
223                    PortletContext portletContext = portletConfig.getPortletContext();
224    
225                    InvokerPortlet invokerPortlet = _invokerPortletFactory.create(
226                            portlet, portletInstance, portletContext);
227    
228                    invokerPortlet.init(portletConfig);
229    
230                    return invokerPortlet;
231            }
232    
233            private InvokerPortletFactory _invokerPortletFactory;
234            private Map<String, Map<String, InvokerPortlet>> _pool;
235    
236    }