1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.factory;
18
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.Map;
23
24 import javax.portlet.Portlet;
25 import javax.portlet.PortletConfig;
26 import javax.portlet.PortletContext;
27 import javax.portlet.PortletException;
28 import javax.portlet.PreferencesValidator;
29 import javax.portlet.UnavailableException;
30 import javax.servlet.ServletContext;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.jetspeed.container.JetspeedPortletConfig;
35 import org.apache.jetspeed.container.PortalAccessor;
36 import org.apache.jetspeed.om.common.portlet.PortletApplication;
37 import org.apache.jetspeed.om.common.portlet.PortletDefinitionComposite;
38 import org.apache.pluto.om.portlet.PortletDefinition;
39
40 /***
41 * <p>
42 * JetspeedPortletFactory
43 * </p>
44 * <p>
45 *
46 * </p>
47 * @author <a href="mailto:weaver@apache.org">Scott T. Weaver</a>
48 * @version $Id: JetspeedPortletFactory.java 516448 2007-03-09 16:25:47Z ate $
49 *
50 */
51 public class JetspeedPortletFactory implements PortletFactory
52 {
53
54 private Map portletCache;
55 private Map validatorCache;
56
57 private static final Log log = LogFactory.getLog(JetspeedPortletFactory.class);
58 private final Map classLoaderMap;
59
60 /***
61 *
62 */
63 public JetspeedPortletFactory()
64 {
65 this.portletCache = Collections.synchronizedMap(new HashMap());
66 this.validatorCache = Collections.synchronizedMap(new HashMap());
67 classLoaderMap = Collections.synchronizedMap(new HashMap());
68 }
69
70 public void registerPortletApplication(PortletApplication pa, ClassLoader cl)
71 {
72 synchronized (classLoaderMap)
73 {
74 unregisterPortletApplication(pa);
75 classLoaderMap.put(pa.getId(), cl);
76 }
77 }
78
79 public void unregisterPortletApplication(PortletApplication pa)
80 {
81 synchronized (classLoaderMap)
82 {
83 synchronized (portletCache)
84 {
85 ClassLoader cl = (ClassLoader) classLoaderMap.remove(pa.getId());
86 if (cl != null)
87 {
88 ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
89
90 Iterator portletDefinitions = pa.getPortletDefinitions().iterator();
91 while (portletDefinitions.hasNext())
92 {
93 PortletDefinition pd = (PortletDefinition) portletDefinitions.next();
94 String pdId = pd.getId().toString();
95 Portlet portlet = (Portlet) portletCache.remove(pdId);
96 if (portlet != null)
97 {
98 try
99 {
100 Thread.currentThread().setContextClassLoader(cl);
101 portlet.destroy();
102 }
103 finally
104 {
105 Thread.currentThread().setContextClassLoader(currentContextClassLoader);
106 }
107 }
108 validatorCache.remove(pdId);
109 }
110 }
111 }
112 }
113 }
114
115 public PreferencesValidator getPreferencesValidator(PortletDefinition pd)
116 {
117 PreferencesValidator validator = null;
118 try
119 {
120 String pdId = pd.getId().toString();
121
122 synchronized (validatorCache)
123 {
124 validator = (PreferencesValidator)validatorCache.get(pdId);
125 if ( validator == null )
126 {
127 String className = ((PortletDefinitionComposite)pd).getPreferenceValidatorClassname();
128 if ( className != null )
129 {
130 PortletApplication pa = (PortletApplication)pd.getPortletApplicationDefinition();
131 ClassLoader paCl = (ClassLoader)classLoaderMap.get(pa.getId());
132 if ( paCl == null )
133 {
134 throw new UnavailableException("Portlet Application "+pa.getName()+" not available");
135 }
136
137 ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
138 try
139 {
140 Class clazz = paCl.loadClass(className);
141 try
142 {
143 Thread.currentThread().setContextClassLoader(paCl);
144 validator = (PreferencesValidator)clazz.newInstance();
145 validatorCache.put(pdId, validator);
146 }
147 finally
148 {
149 Thread.currentThread().setContextClassLoader(currentContextClassLoader);
150 }
151 }
152 catch (Exception e)
153 {
154 String msg = "Cannot create PreferencesValidator instance "+className+" for Portlet "+pd.getName();
155 log.error(msg,e);
156 }
157 }
158 }
159 }
160 }
161 catch (Exception e)
162 {
163 log.error(e);
164 }
165 return validator;
166 }
167
168 /***
169 * Gets a portlet by either creating it or returning a handle to it from the portlet 'cache'
170 *
171 * @param portletDefinition The definition of the portlet
172 * @return PortletInstance
173 * @throws PortletException
174 */
175 public PortletInstance getPortletInstance( ServletContext servletContext, PortletDefinition pd ) throws PortletException
176 {
177 PortletInstance portlet = null;
178 String pdId = pd.getId().toString();
179 PortletApplication pa = (PortletApplication)pd.getPortletApplicationDefinition();
180
181 try
182 {
183 synchronized (portletCache)
184 {
185 portlet = (PortletInstance)portletCache.get(pdId);
186 if (null != portlet)
187 {
188 return portlet;
189 }
190
191 ClassLoader paCl = (ClassLoader)classLoaderMap.get(pa.getId());
192 if ( paCl == null )
193 {
194 throw new UnavailableException("Portlet Application "+pa.getName()+" not available");
195 }
196
197 ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
198
199 try
200 {
201 Class clazz = paCl.loadClass(pd.getClassName());
202 try
203 {
204 Thread.currentThread().setContextClassLoader(paCl);
205
206
207
208 portlet = new JetspeedPortletInstance(pd.getName(), (Portlet)clazz.newInstance());
209 }
210 finally
211 {
212 Thread.currentThread().setContextClassLoader(currentContextClassLoader);
213 }
214 }
215 catch (Exception e)
216 {
217 String msg = "Cannot create Portlet instance "+pd.getClassName()+" for Portlet Application "+pa.getName();
218 log.error(msg,e);
219 throw new UnavailableException(msg);
220 }
221
222 PortletContext portletContext = PortalAccessor.createPortletContext(servletContext, pa);
223 PortletConfig portletConfig = PortalAccessor.createPortletConfig(portletContext, pd);
224
225 try
226 {
227 try
228 {
229 Thread.currentThread().setContextClassLoader(paCl);
230 portlet.init(portletConfig);
231 }
232 finally
233 {
234 Thread.currentThread().setContextClassLoader(currentContextClassLoader);
235 }
236 }
237 catch (PortletException e1)
238 {
239 log.error("Failed to initialize Portlet "+pd.getClassName()+" for Portlet Application "+pa.getName(), e1);
240 throw e1;
241 }
242 portletCache.put(pdId, portlet);
243 }
244 }
245 catch (PortletException pe)
246 {
247 throw pe;
248 }
249 catch (Throwable e)
250 {
251 log.error("PortletFactory: Failed to load portlet "+pd.getClassName(), e);
252 throw new UnavailableException( "Failed to load portlet " + pd.getClassName() +": "+e.toString());
253 }
254 return portlet;
255 }
256
257 public void updatePortletConfig(PortletDefinition pd)
258 {
259 if (pd != null)
260 {
261
262 String key = pd.getId().toString();
263 PortletInstance instance = (PortletInstance)portletCache.get(key);
264 if (instance != null)
265 {
266 JetspeedPortletConfig config = (JetspeedPortletConfig)instance.getConfig();
267 config.setPortletDefinition(pd);
268 }
269 }
270 }
271
272 public ClassLoader getPortletApplicationClassLoader(PortletApplication pa)
273 {
274 synchronized (classLoaderMap)
275 {
276 if ( pa != null )
277 {
278 return (ClassLoader)classLoaderMap.get(pa.getId());
279 }
280 return null;
281 }
282 }
283
284 public boolean isPortletApplicationRegistered(PortletApplication pa)
285 {
286 return getPortletApplicationClassLoader(pa) != null;
287 }
288 }