1   /**
2    * Copyright (c) 2000-2010 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   *
12   * 
13   */
14  
15  package com.liferay.portlet;
16  
17  import com.liferay.portal.kernel.portlet.PortletBag;
18  import com.liferay.portal.kernel.portlet.PortletBagPool;
19  import com.liferay.portal.model.Portlet;
20  import com.liferay.portal.model.PortletApp;
21  import com.liferay.portal.model.PortletConstants;
22  import com.liferay.portal.service.PortletLocalServiceUtil;
23  
24  import java.util.Iterator;
25  import java.util.Map;
26  import java.util.concurrent.ConcurrentHashMap;
27  
28  import javax.portlet.PortletConfig;
29  import javax.portlet.PortletContext;
30  import javax.portlet.PortletException;
31  import javax.portlet.UnavailableException;
32  
33  import javax.servlet.ServletContext;
34  
35  /**
36   * <a href="PortletInstanceFactory.java.html"><b><i>View Source</i></b></a>
37   *
38   * @author Brian Wing Shun Chan
39   */
40  public class PortletInstanceFactory {
41  
42      public static InvokerPortlet create(
43              Portlet portlet, ServletContext servletContext)
44          throws PortletException {
45  
46          return _instance._create(portlet, servletContext);
47      }
48  
49      public static void destroy(Portlet portlet) {
50          _instance._destroy(portlet);
51      }
52  
53      public void setInternalInvokerPortletPrototype(
54          InvokerPortlet internalInvokerPortletPrototype) {
55  
56          _internalInvokerPortletPrototype = internalInvokerPortletPrototype;
57      }
58  
59      private PortletInstanceFactory() {
60          _pool = new ConcurrentHashMap<String, Map<String, InvokerPortlet>>();
61      }
62  
63      private InvokerPortlet _create(
64              Portlet portlet, ServletContext servletContext)
65          throws PortletException {
66  
67          boolean instanceable = false;
68  
69          if ((portlet.isInstanceable()) &&
70              (PortletConstants.getInstanceId(portlet.getPortletId()) != null)) {
71  
72              instanceable = true;
73          }
74  
75          Map<String, InvokerPortlet> portletInstances = _pool.get(
76              portlet.getRootPortletId());
77  
78          if (portletInstances == null) {
79              portletInstances = new ConcurrentHashMap<String, InvokerPortlet>();
80  
81              _pool.put(portlet.getRootPortletId(), portletInstances);
82          }
83  
84          InvokerPortlet instanceInvokerPortletInstance = null;
85  
86          if (instanceable) {
87              instanceInvokerPortletInstance = portletInstances.get(
88                  portlet.getPortletId());
89          }
90  
91          InvokerPortlet rootInvokerPortletInstance = null;
92  
93          if (instanceInvokerPortletInstance == null) {
94              rootInvokerPortletInstance = portletInstances.get(
95                  portlet.getRootPortletId());
96  
97              if (rootInvokerPortletInstance == null) {
98                  PortletConfig portletConfig =
99                      PortletConfigFactory.create(portlet, servletContext);
100 
101                 PortletApp portletApp = portlet.getPortletApp();
102 
103                 if (portletApp.isWARFile()) {
104                     PortletBag portletBag = PortletBagPool.get(
105                         portlet.getRootPortletId());
106 
107                     rootInvokerPortletInstance = _init(
108                         portlet, portletConfig,
109                         portletBag.getPortletInstance());
110                 }
111                 else {
112                     rootInvokerPortletInstance = _init(portlet, portletConfig);
113                 }
114 
115                 portletInstances.put(
116                     portlet.getRootPortletId(), rootInvokerPortletInstance);
117             }
118         }
119 
120         if (instanceable) {
121             if (instanceInvokerPortletInstance == null) {
122                 javax.portlet.Portlet portletInstance =
123                     rootInvokerPortletInstance.getPortletInstance();
124 
125                 PortletConfig portletConfig =
126                     PortletConfigFactory.create(portlet, servletContext);
127 
128                 PortletContext portletContext =
129                     portletConfig.getPortletContext();
130                 boolean facesPortlet =
131                     rootInvokerPortletInstance.isFacesPortlet();
132                 boolean strutsPortlet =
133                     rootInvokerPortletInstance.isStrutsPortlet();
134                 boolean strutsBridgePortlet =
135                     rootInvokerPortletInstance.isStrutsBridgePortlet();
136 
137                 instanceInvokerPortletInstance =
138                     _internalInvokerPortletPrototype.create(
139                         portlet, portletInstance, portletConfig, portletContext,
140                         facesPortlet, strutsPortlet, strutsBridgePortlet);
141 
142                 portletInstances.put(
143                     portlet.getPortletId(), instanceInvokerPortletInstance);
144             }
145         }
146         else {
147             if (rootInvokerPortletInstance != null) {
148                 instanceInvokerPortletInstance = rootInvokerPortletInstance;
149             }
150         }
151 
152         return instanceInvokerPortletInstance;
153     }
154 
155     private void _destroy(Portlet portlet) {
156         Map<String, InvokerPortlet> portletInstances = _pool.get(
157             portlet.getRootPortletId());
158 
159         if (portletInstances != null) {
160             Iterator<Map.Entry<String, InvokerPortlet>> itr =
161                 portletInstances.entrySet().iterator();
162 
163             while (itr.hasNext()) {
164                 Map.Entry<String, InvokerPortlet> entry = itr.next();
165 
166                 String portletId = entry.getKey();
167                 InvokerPortlet invokerPortletInstance = entry.getValue();
168 
169                 if (PortletConstants.getInstanceId(portletId) == null) {
170                     invokerPortletInstance.destroy();
171 
172                     break;
173                 }
174             }
175         }
176 
177         _pool.remove(portlet.getRootPortletId());
178 
179         PortletApp portletApp = portlet.getPortletApp();
180 
181         if (portletApp.isWARFile()) {
182             PortletBag portletBag = PortletBagPool.get(
183                 portlet.getRootPortletId());
184 
185             if (portletBag != null) {
186                 portletBag.setPortletInstance(null);
187             }
188         }
189 
190         PortletConfigFactory.destroy(portlet);
191         PortletContextFactory.destroy(portlet);
192 
193         PortletLocalServiceUtil.destroyPortlet(portlet);
194     }
195 
196     private InvokerPortlet _init(Portlet portlet, PortletConfig portletConfig)
197         throws PortletException {
198 
199         return _init(portlet, portletConfig, null);
200     }
201 
202     private InvokerPortlet _init(
203             Portlet portlet, PortletConfig portletConfig,
204             javax.portlet.Portlet portletInstance)
205         throws PortletException {
206 
207         InvokerPortlet invokerPortlet = null;
208 
209         try {
210             if (portletInstance == null) {
211                 portletInstance =
212                     (javax.portlet.Portlet)Class.forName(
213                         portlet.getPortletClass()).newInstance();
214             }
215 
216             PortletContext portletContext = portletConfig.getPortletContext();
217 
218             invokerPortlet = _internalInvokerPortletPrototype.create(
219                 portlet, portletInstance, portletContext);
220 
221             invokerPortlet.init(portletConfig);
222         }
223         catch (ClassNotFoundException cnofe) {
224             throw new UnavailableException(cnofe.getMessage());
225         }
226         catch (InstantiationException ie) {
227             throw new UnavailableException(ie.getMessage());
228         }
229         catch (IllegalAccessException iae) {
230             throw new UnavailableException(iae.getMessage());
231         }
232 
233         return invokerPortlet;
234     }
235 
236     private static PortletInstanceFactory _instance =
237         new PortletInstanceFactory();
238 
239     private static InvokerPortlet _internalInvokerPortletPrototype;
240 
241     private Map<String, Map<String, InvokerPortlet>> _pool;
242 
243 }