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