001    /**
002     * Copyright (c) 2000-2010 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.util.PortalClassLoaderUtil;
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    
025    import java.util.Iterator;
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     */
038    public class PortletInstanceFactoryImpl implements PortletInstanceFactory {
039    
040            public PortletInstanceFactoryImpl() {
041                    _pool = new ConcurrentHashMap<String, Map<String, InvokerPortlet>>();
042            }
043    
044            public void clear(Portlet portlet) {
045                    clear(portlet, true);
046            }
047    
048            public void clear(Portlet portlet, boolean resetRemotePortletBag) {
049                    Map<String, InvokerPortlet> portletInstances = _pool.get(
050                            portlet.getRootPortletId());
051    
052                    if (portletInstances != null) {
053                            Iterator<Map.Entry<String, InvokerPortlet>> itr =
054                                    portletInstances.entrySet().iterator();
055    
056                            while (itr.hasNext()) {
057                                    Map.Entry<String, InvokerPortlet> entry = itr.next();
058    
059                                    String portletId = entry.getKey();
060                                    InvokerPortlet invokerPortletInstance = entry.getValue();
061    
062                                    if (PortletConstants.getInstanceId(portletId) == null) {
063                                            invokerPortletInstance.destroy();
064    
065                                            break;
066                                    }
067                            }
068                    }
069    
070                    _pool.remove(portlet.getRootPortletId());
071    
072                    PortletApp portletApp = portlet.getPortletApp();
073    
074                    if (resetRemotePortletBag && portletApp.isWARFile()) {
075                            PortletBagPool.remove(portlet.getRootPortletId());
076                    }
077            }
078    
079            public InvokerPortlet create(Portlet portlet, ServletContext servletContext)
080                    throws PortletException {
081    
082                    boolean instanceable = false;
083    
084                    if ((portlet.isInstanceable()) &&
085                            (PortletConstants.getInstanceId(portlet.getPortletId()) != null)) {
086    
087                            instanceable = true;
088                    }
089    
090                    Map<String, InvokerPortlet> portletInstances = _pool.get(
091                            portlet.getRootPortletId());
092    
093                    if (portletInstances == null) {
094                            portletInstances = new ConcurrentHashMap<String, InvokerPortlet>();
095    
096                            _pool.put(portlet.getRootPortletId(), portletInstances);
097                    }
098    
099                    InvokerPortlet instanceInvokerPortletInstance = null;
100    
101                    if (instanceable) {
102                            instanceInvokerPortletInstance = portletInstances.get(
103                                    portlet.getPortletId());
104                    }
105    
106                    InvokerPortlet rootInvokerPortletInstance = null;
107    
108                    if (instanceInvokerPortletInstance == null) {
109                            rootInvokerPortletInstance = portletInstances.get(
110                                    portlet.getRootPortletId());
111    
112                            if (rootInvokerPortletInstance == null) {
113                                    PortletBag portletBag = PortletBagPool.get(
114                                            portlet.getRootPortletId());
115    
116                                    // Portlet bag should never be null unless the portlet has been
117                                    // undeployed
118    
119                                    if (portletBag == null) {
120                                            PortletBagFactory portletBagFactory =
121                                                    new PortletBagFactory();
122    
123                                            portletBagFactory.setClassLoader(
124                                                    PortalClassLoaderUtil.getClassLoader());
125                                            portletBagFactory.setServletContext(servletContext);
126                                            portletBagFactory.setWARFile(false);
127    
128                                            try {
129                                                    portletBag = portletBagFactory.create(portlet);
130                                            }
131                                            catch (Exception e) {
132                                                    throw new PortletException(e);
133                                            }
134                                    }
135    
136                                    PortletConfig portletConfig = PortletConfigFactoryUtil.create(
137                                            portlet, servletContext);
138    
139                                    rootInvokerPortletInstance = init(
140                                            portlet, portletConfig, portletBag.getPortletInstance());
141    
142                                    portletInstances.put(
143                                            portlet.getRootPortletId(), rootInvokerPortletInstance);
144                            }
145                    }
146    
147                    if (instanceable) {
148                            if (instanceInvokerPortletInstance == null) {
149                                    javax.portlet.Portlet portletInstance =
150                                            rootInvokerPortletInstance.getPortletInstance();
151    
152                                    PortletConfig portletConfig =
153                                            PortletConfigFactoryUtil.create(portlet, servletContext);
154    
155                                    PortletContext portletContext =
156                                            portletConfig.getPortletContext();
157                                    boolean checkAuthToken =
158                                            rootInvokerPortletInstance.isCheckAuthToken();
159                                    boolean facesPortlet =
160                                            rootInvokerPortletInstance.isFacesPortlet();
161                                    boolean strutsPortlet =
162                                            rootInvokerPortletInstance.isStrutsPortlet();
163                                    boolean strutsBridgePortlet =
164                                            rootInvokerPortletInstance.isStrutsBridgePortlet();
165    
166                                    instanceInvokerPortletInstance =
167                                            _internalInvokerPortletPrototype.create(
168                                                    portlet, portletInstance, portletConfig, portletContext,
169                                                    checkAuthToken, facesPortlet, strutsPortlet,
170                                                    strutsBridgePortlet);
171    
172                                    portletInstances.put(
173                                            portlet.getPortletId(), instanceInvokerPortletInstance);
174                            }
175                    }
176                    else {
177                            if (rootInvokerPortletInstance != null) {
178                                    instanceInvokerPortletInstance = rootInvokerPortletInstance;
179                            }
180                    }
181    
182                    return instanceInvokerPortletInstance;
183            }
184    
185            public void destroy() {
186    
187                    // LPS-10473
188    
189            }
190    
191            public void destroy(Portlet portlet) {
192                    clear(portlet);
193    
194                    PortletConfigFactoryUtil.destroy(portlet);
195                    PortletContextFactory.destroy(portlet);
196    
197                    PortletLocalServiceUtil.destroyPortlet(portlet);
198            }
199    
200            public void setInternalInvokerPortletPrototype(
201                    InvokerPortlet internalInvokerPortletPrototype) {
202    
203                    _internalInvokerPortletPrototype = internalInvokerPortletPrototype;
204            }
205    
206            protected InvokerPortlet init(
207                            Portlet portlet, PortletConfig portletConfig,
208                            javax.portlet.Portlet portletInstance)
209                    throws PortletException {
210    
211                    PortletContext portletContext = portletConfig.getPortletContext();
212    
213                    InvokerPortlet invokerPortlet = _internalInvokerPortletPrototype.create(
214                            portlet, portletInstance, portletContext);
215    
216                    invokerPortlet.init(portletConfig);
217    
218                    return invokerPortlet;
219            }
220    
221            private InvokerPortlet _internalInvokerPortletPrototype;
222            private Map<String, Map<String, InvokerPortlet>> _pool;
223    
224    }