1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet;
24  
25  import com.liferay.portal.kernel.portlet.PortletBag;
26  import com.liferay.portal.kernel.portlet.PortletBagPool;
27  import com.liferay.portal.model.Portlet;
28  import com.liferay.portal.model.PortletApp;
29  import com.liferay.portal.model.PortletConstants;
30  import com.liferay.portal.service.PortletLocalServiceUtil;
31  import com.liferay.portal.util.PropsValues;
32  
33  import java.util.Iterator;
34  import java.util.Map;
35  import java.util.concurrent.ConcurrentHashMap;
36  
37  import javax.portlet.PortletConfig;
38  import javax.portlet.PortletContext;
39  import javax.portlet.PortletException;
40  import javax.portlet.UnavailableException;
41  
42  import javax.servlet.ServletContext;
43  
44  /**
45   * <a href="PortletInstanceFactory.java.html"><b><i>View Source</i></b></a>
46   *
47   * @author Brian Wing Shun Chan
48   *
49   */
50  public class PortletInstanceFactory {
51  
52      public static InvokerPortlet create(
53              Portlet portlet, ServletContext servletContext)
54          throws PortletException {
55  
56          return _instance._create(portlet, servletContext);
57      }
58  
59      public static void destroy(Portlet portlet) {
60          _instance._destroy(portlet);
61      }
62  
63      public void setInternalInvokerPortletPrototype(
64          InvokerPortlet internalInvokerPortletPrototype) {
65  
66          _internalInvokerPortletPrototype = internalInvokerPortletPrototype;
67      }
68  
69      public void setSunInvokerPortletPrototype(
70          InvokerPortlet sunInvokerPortletPrototype) {
71  
72          _sunInvokerPortletPrototype = sunInvokerPortletPrototype;
73      }
74  
75      private PortletInstanceFactory() {
76          _pool = new ConcurrentHashMap<String, Map<String, InvokerPortlet>>();
77      }
78  
79      private InvokerPortlet _create(
80              Portlet portlet, ServletContext servletContext)
81          throws PortletException {
82  
83          boolean instanceable = false;
84  
85          if ((portlet.isInstanceable()) &&
86              (PortletConstants.getInstanceId(portlet.getPortletId()) != null)) {
87  
88              instanceable = true;
89          }
90  
91          Map<String, InvokerPortlet> portletInstances = _pool.get(
92              portlet.getRootPortletId());
93  
94          if (portletInstances == null) {
95              portletInstances = new ConcurrentHashMap<String, InvokerPortlet>();
96  
97              _pool.put(portlet.getRootPortletId(), portletInstances);
98          }
99  
100         InvokerPortlet instanceInvokerPortletInstance = null;
101 
102         if (instanceable) {
103             instanceInvokerPortletInstance = portletInstances.get(
104                 portlet.getPortletId());
105         }
106 
107         InvokerPortlet rootInvokerPortletInstance = null;
108 
109         if (instanceInvokerPortletInstance == null) {
110             rootInvokerPortletInstance = portletInstances.get(
111                 portlet.getRootPortletId());
112 
113             if (rootInvokerPortletInstance == null) {
114                 PortletConfig portletConfig =
115                     PortletConfigFactory.create(portlet, servletContext);
116 
117                 PortletApp portletApp = portlet.getPortletApp();
118 
119                 if (portletApp.isWARFile()) {
120                     PortletBag portletBag = PortletBagPool.get(
121                         portlet.getRootPortletId());
122 
123                     rootInvokerPortletInstance = _init(
124                         portlet, portletConfig,
125                         portletBag.getPortletInstance());
126                 }
127                 else {
128                     rootInvokerPortletInstance = _init(portlet, portletConfig);
129                 }
130 
131                 portletInstances.put(
132                     portlet.getRootPortletId(), rootInvokerPortletInstance);
133             }
134         }
135 
136         if (instanceable) {
137             if (instanceInvokerPortletInstance == null) {
138                 javax.portlet.Portlet portletInstance =
139                     rootInvokerPortletInstance.getPortletInstance();
140 
141                 PortletConfig portletConfig =
142                     PortletConfigFactory.create(portlet, servletContext);
143 
144                 PortletContext portletContext =
145                     portletConfig.getPortletContext();
146                 boolean facesPortlet =
147                     rootInvokerPortletInstance.isFacesPortlet();
148                 boolean strutsPortlet =
149                     rootInvokerPortletInstance.isStrutsPortlet();
150                 boolean strutsBridgePortlet =
151                     rootInvokerPortletInstance.isStrutsBridgePortlet();
152 
153                 if (PropsValues.PORTLET_CONTAINER_IMPL_SUN) {
154                     instanceInvokerPortletInstance =
155                         _sunInvokerPortletPrototype.create(
156                             portlet, portletInstance, portletConfig,
157                             portletContext, facesPortlet, strutsPortlet,
158                             strutsBridgePortlet);
159                 }
160                 else {
161                     instanceInvokerPortletInstance =
162                         _internalInvokerPortletPrototype.create(
163                             portlet, portletInstance, portletConfig,
164                             portletContext, facesPortlet, strutsPortlet,
165                             strutsBridgePortlet);
166                 }
167 
168                 portletInstances.put(
169                     portlet.getPortletId(), instanceInvokerPortletInstance);
170             }
171         }
172         else {
173             if (rootInvokerPortletInstance != null) {
174                 instanceInvokerPortletInstance = rootInvokerPortletInstance;
175             }
176         }
177 
178         return instanceInvokerPortletInstance;
179     }
180 
181     private void _destroy(Portlet portlet) {
182         Map<String, InvokerPortlet> portletInstances = _pool.get(
183             portlet.getRootPortletId());
184 
185         if (portletInstances == null) {
186             return;
187         }
188 
189         Iterator<Map.Entry<String, InvokerPortlet>> itr =
190             portletInstances.entrySet().iterator();
191 
192         while (itr.hasNext()) {
193             Map.Entry<String, InvokerPortlet> entry = itr.next();
194 
195             String portletId = entry.getKey();
196             InvokerPortlet invokerPortletInstance = entry.getValue();
197 
198             if (PortletConstants.getInstanceId(portletId) == null) {
199                 invokerPortletInstance.destroy();
200 
201                 break;
202             }
203         }
204 
205         _pool.remove(portlet.getRootPortletId());
206 
207         PortletApp portletApp = portlet.getPortletApp();
208 
209         if (portletApp.isWARFile()) {
210             PortletBag portletBag = PortletBagPool.get(
211                 portlet.getRootPortletId());
212 
213             portletBag.removePortletInstance();
214         }
215 
216         PortletConfigFactory.destroy(portlet);
217         PortletContextFactory.destroy(portlet);
218 
219         PortletLocalServiceUtil.destroyPortlet(portlet);
220     }
221 
222     private InvokerPortlet _init(Portlet portlet, PortletConfig portletConfig)
223         throws PortletException {
224 
225         return _init(portlet, portletConfig, null);
226     }
227 
228     private InvokerPortlet _init(
229             Portlet portlet, PortletConfig portletConfig,
230             javax.portlet.Portlet portletInstance)
231         throws PortletException {
232 
233         InvokerPortlet invokerPortlet = null;
234 
235         try {
236             if (portletInstance == null) {
237                 portletInstance =
238                     (javax.portlet.Portlet)Class.forName(
239                         portlet.getPortletClass()).newInstance();
240             }
241 
242             PortletContext portletContext = portletConfig.getPortletContext();
243 
244             if (PropsValues.PORTLET_CONTAINER_IMPL_SUN) {
245                 invokerPortlet = _sunInvokerPortletPrototype.create(
246                     portlet, portletInstance, portletContext);
247             }
248             else {
249                 invokerPortlet = _internalInvokerPortletPrototype.create(
250                     portlet, portletInstance, portletContext);
251             }
252 
253             invokerPortlet.init(portletConfig);
254         }
255         catch (ClassNotFoundException cnofe) {
256             throw new UnavailableException(cnofe.getMessage());
257         }
258         catch (InstantiationException ie) {
259             throw new UnavailableException(ie.getMessage());
260         }
261         catch (IllegalAccessException iae) {
262             throw new UnavailableException(iae.getMessage());
263         }
264 
265         return invokerPortlet;
266     }
267 
268     private static PortletInstanceFactory _instance =
269         new PortletInstanceFactory();
270 
271     private static InvokerPortlet _internalInvokerPortletPrototype;
272     private static InvokerPortlet _sunInvokerPortletPrototype;
273 
274     private Map<String, Map<String, InvokerPortlet>> _pool;
275 
276 }