1
22
23 package com.liferay.portal.deploy.hot;
24
25 import com.liferay.portal.apache.bridges.struts.LiferayServletContextProvider;
26 import com.liferay.portal.job.Scheduler;
27 import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
28 import com.liferay.portal.kernel.deploy.hot.HotDeployException;
29 import com.liferay.portal.kernel.deploy.hot.HotDeployListener;
30 import com.liferay.portal.kernel.language.LanguageUtil;
31 import com.liferay.portal.kernel.lar.PortletDataHandler;
32 import com.liferay.portal.kernel.portlet.ConfigurationAction;
33 import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
34 import com.liferay.portal.kernel.portlet.PortletLayoutListener;
35 import com.liferay.portal.kernel.search.Indexer;
36 import com.liferay.portal.kernel.servlet.PortletServlet;
37 import com.liferay.portal.kernel.servlet.ServletContextProvider;
38 import com.liferay.portal.kernel.servlet.URLEncoder;
39 import com.liferay.portal.kernel.smtp.MessageListener;
40 import com.liferay.portal.kernel.util.ClassUtil;
41 import com.liferay.portal.kernel.util.GetterUtil;
42 import com.liferay.portal.kernel.util.LocaleUtil;
43 import com.liferay.portal.kernel.util.ObjectValuePair;
44 import com.liferay.portal.kernel.util.PropertiesUtil;
45 import com.liferay.portal.kernel.util.StringUtil;
46 import com.liferay.portal.kernel.util.Validator;
47 import com.liferay.portal.model.Portlet;
48 import com.liferay.portal.model.PortletCategory;
49 import com.liferay.portal.security.permission.ResourceActionsUtil;
50 import com.liferay.portal.service.PortletLocalServiceUtil;
51 import com.liferay.portal.service.ServiceComponentLocalServiceUtil;
52 import com.liferay.portal.servlet.PortletContextPool;
53 import com.liferay.portal.servlet.PortletContextWrapper;
54 import com.liferay.portal.smtp.SMTPServerUtil;
55 import com.liferay.portal.util.PortalInstances;
56 import com.liferay.portal.util.PortalUtil;
57 import com.liferay.portal.util.PropsUtil;
58 import com.liferay.portal.util.WebAppPool;
59 import com.liferay.portal.util.WebKeys;
60 import com.liferay.portlet.PortletInstanceFactory;
61 import com.liferay.portlet.PortletPreferencesSerializer;
62 import com.liferay.portlet.PortletResourceBundles;
63 import com.liferay.util.CollectionFactory;
64 import com.liferay.util.Http;
65
66 import java.util.HashSet;
67 import java.util.Iterator;
68 import java.util.List;
69 import java.util.Locale;
70 import java.util.Map;
71 import java.util.MissingResourceException;
72 import java.util.Properties;
73 import java.util.ResourceBundle;
74 import java.util.Set;
75
76 import javax.portlet.PreferencesValidator;
77
78 import javax.servlet.ServletContext;
79
80 import org.apache.commons.logging.Log;
81 import org.apache.commons.logging.LogFactory;
82 import org.apache.portals.bridges.struts.StrutsPortlet;
83
84
92 public class PortletHotDeployListener implements HotDeployListener {
93
94 public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
95 String servletContextName = null;
96
97 try {
98
99
101 ServletContext ctx = event.getServletContext();
102
103 servletContextName = ctx.getServletContextName();
104
105 if (_log.isDebugEnabled()) {
106 _log.debug("Invoking deploy for " + servletContextName);
107 }
108
109
111 long[] companyIds = PortalInstances.getCompanyIds();
112
113
115 String[] xmls = new String[] {
116 Http.URLtoString(ctx.getResource(
117 "/WEB-INF/" + PortalUtil.PORTLET_XML_FILE_NAME_STANDARD)),
118 Http.URLtoString(ctx.getResource(
119 "/WEB-INF/" + PortalUtil.PORTLET_XML_FILE_NAME_CUSTOM)),
120 Http.URLtoString(ctx.getResource(
121 "/WEB-INF/liferay-portlet.xml")),
122 Http.URLtoString(ctx.getResource("/WEB-INF/web.xml"))
123 };
124
125 if (xmls[0] == null) {
126 return;
127 }
128
129 if (_log.isInfoEnabled()) {
130 _log.info("Registering portlets for " + servletContextName);
131 }
132
133 List portlets = PortletLocalServiceUtil.initWAR(
134 servletContextName, xmls, event.getPluginPackage());
135
136
138 ClassLoader portletClassLoader = event.getContextClassLoader();
139
140 ctx.setAttribute(
141 PortletServlet.PORTLET_CLASS_LOADER, portletClassLoader);
142
143
145 boolean strutsBridges = false;
146
147 Iterator itr1 = portlets.iterator();
148
149 while (itr1.hasNext()) {
150 Portlet portlet = (Portlet)itr1.next();
151
152 Class portletClass = portletClassLoader.loadClass(
153 portlet.getPortletClass());
154
155 javax.portlet.Portlet portletInstance =
156 (javax.portlet.Portlet)portletClass.newInstance();
157
158 if (ClassUtil.isSubclass(portletClass,
159 StrutsPortlet.class.getName())) {
160
161 strutsBridges = true;
162 }
163
164 ConfigurationAction configurationActionInstance = null;
165
166 if (Validator.isNotNull(
167 portlet.getConfigurationActionClass())) {
168
169 configurationActionInstance =
170 (ConfigurationAction)portletClassLoader.loadClass(
171 portlet.getConfigurationActionClass()).
172 newInstance();
173 }
174
175 Indexer indexerInstance = null;
176
177 if (Validator.isNotNull(portlet.getIndexerClass())) {
178 indexerInstance = (Indexer)portletClassLoader.loadClass(
179 portlet.getIndexerClass()).newInstance();
180 }
181
182 Scheduler schedulerInstance = null;
183
184 if (Validator.isNotNull(portlet.getSchedulerClass())) {
185 schedulerInstance = (Scheduler)portletClassLoader.loadClass(
186 portlet.getSchedulerClass()).newInstance();
187 }
188
189 FriendlyURLMapper friendlyURLMapperInstance = null;
190
191 if (Validator.isNotNull(portlet.getFriendlyURLMapperClass())) {
192 friendlyURLMapperInstance =
193 (FriendlyURLMapper)portletClassLoader.loadClass(
194 portlet.getFriendlyURLMapperClass()).newInstance();
195 }
196
197 URLEncoder urlEncoderInstance = null;
198
199 if (Validator.isNotNull(portlet.getURLEncoderClass())) {
200 urlEncoderInstance =
201 (URLEncoder)portletClassLoader.loadClass(
202 portlet.getURLEncoderClass()).newInstance();
203 }
204
205 PortletDataHandler portletDataHandlerInstance = null;
206
207 if (Validator.isNotNull(portlet.getPortletDataHandlerClass())) {
208 portletDataHandlerInstance =
209 (PortletDataHandler)portletClassLoader.loadClass(
210 portlet.getPortletDataHandlerClass()).newInstance();
211 }
212
213 PortletLayoutListener portletLayoutListenerInstance = null;
214
215 if (Validator.isNotNull(
216 portlet.getPortletLayoutListenerClass())) {
217
218 portletLayoutListenerInstance =
219 (PortletLayoutListener)portletClassLoader.loadClass(
220 portlet.getPortletLayoutListenerClass()).
221 newInstance();
222 }
223
224 MessageListener smtpMessageListenerInstance = null;
225
226 if (Validator.isNotNull(
227 portlet.getSmtpMessageListenerClass())) {
228
229 smtpMessageListenerInstance =
230 (MessageListener)portletClassLoader.loadClass(
231 portlet.getSmtpMessageListenerClass()).
232 newInstance();
233
234 SMTPServerUtil.addListener(smtpMessageListenerInstance);
235 }
236
237 PreferencesValidator prefsValidatorInstance = null;
238
239 if (Validator.isNotNull(portlet.getPreferencesValidator())) {
240 prefsValidatorInstance =
241 (PreferencesValidator)portletClassLoader.loadClass(
242 portlet.getPreferencesValidator()).newInstance();
243
244 try {
245 if (GetterUtil.getBoolean(PropsUtil.get(
246 PropsUtil.PREFERENCE_VALIDATE_ON_STARTUP))) {
247
248 prefsValidatorInstance.validate(
249 PortletPreferencesSerializer.fromDefaultXML(
250 portlet.getDefaultPreferences()));
251 }
252 }
253 catch (Exception e1) {
254 _log.warn(
255 "Portlet with the name " + portlet.getPortletId() +
256 " does not have valid default preferences");
257 }
258 }
259
260 Map resourceBundles = null;
261
262 if (Validator.isNotNull(portlet.getResourceBundle())) {
263 resourceBundles = CollectionFactory.getHashMap();
264
265 Iterator itr2 = portlet.getSupportedLocales().iterator();
266
267 while (itr2.hasNext()) {
268 String supportedLocale = (String)itr2.next();
269
270 Locale locale = LocaleUtil.fromLanguageId(
271 supportedLocale);
272
273 try {
274 ResourceBundle resourceBundle =
275 ResourceBundle.getBundle(
276 portlet.getResourceBundle(), locale,
277 portletClassLoader);
278
279 resourceBundles.put(
280 LocaleUtil.toLanguageId(locale),
281 resourceBundle);
282 }
283 catch (MissingResourceException mre) {
284 _log.warn(mre.getMessage());
285 }
286 }
287 }
288
289 Map customUserAttributes = CollectionFactory.getHashMap();
290
291 Iterator itr2 =
292 portlet.getCustomUserAttributes().entrySet().iterator();
293
294 while (itr2.hasNext()) {
295 Map.Entry entry = (Map.Entry)itr2.next();
296
297 String attrCustomClass = (String)entry.getValue();
298
299 customUserAttributes.put(
300 attrCustomClass,
301 portletClassLoader.loadClass(
302 attrCustomClass).newInstance());
303 }
304
305 PortletContextWrapper pcw = new PortletContextWrapper(
306 portlet.getPortletId(), ctx, portletInstance,
307 configurationActionInstance, indexerInstance,
308 schedulerInstance, friendlyURLMapperInstance,
309 urlEncoderInstance, portletDataHandlerInstance,
310 portletLayoutListenerInstance,
311 smtpMessageListenerInstance, prefsValidatorInstance,
312 resourceBundles, customUserAttributes);
313
314 PortletContextPool.put(portlet.getPortletId(), pcw);
315 }
316
317
319 if (!strutsBridges) {
320 strutsBridges = GetterUtil.getBoolean(
321 ctx.getInitParameter("struts-bridges-context-provider"));
322 }
323
324 if (strutsBridges) {
325 ctx.setAttribute(
326 ServletContextProvider.STRUTS_BRIDGES_CONTEXT_PROVIDER,
327 new LiferayServletContextProvider());
328 }
329
330
332 String xml = Http.URLtoString(ctx.getResource(
333 "/WEB-INF/liferay-display.xml"));
334
335 PortletCategory newPortletCategory =
336 PortletLocalServiceUtil.getWARDisplay(servletContextName, xml);
337
338 for (int i = 0; i < companyIds.length; i++) {
339 long companyId = companyIds[i];
340
341 PortletCategory portletCategory =
342 (PortletCategory)WebAppPool.get(
343 String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
344
345 if (portletCategory != null) {
346 portletCategory.merge(newPortletCategory);
347 }
348 else {
349 _log.error(
350 "Unable to register portlet for company " + companyId +
351 " because it does not exist");
352 }
353 }
354
355
357 String portletPropsName = ctx.getInitParameter(
358 "portlet_properties");
359
360 if (Validator.isNotNull(portletPropsName)) {
361 if (_log.isDebugEnabled()) {
362 _log.debug(
363 "Loading portlet properties " + portletPropsName);
364 }
365
366 Properties portletProps = new Properties();
367
368 PropertiesUtil.load(
369 portletProps,
370 StringUtil.read(portletClassLoader, portletPropsName));
371
372 if (_log.isDebugEnabled()) {
373 String portletPropsString = PropertiesUtil.list(
374 portletProps);
375
376 _log.debug(portletPropsString);
377 }
378
379 processProperties(
380 servletContextName, portletClassLoader, portletProps);
381 }
382
383
385 processServiceBuilder(ctx, portletClassLoader);
386
387
389 _vars.put(
390 servletContextName, new ObjectValuePair(companyIds, portlets));
391
392 if (_log.isInfoEnabled()) {
393 _log.info(
394 "Portlets for " + servletContextName +
395 " registered successfully");
396 }
397 }
398 catch (Exception e2) {
399 throw new HotDeployException(
400 "Error registering portlets for " + servletContextName, e2);
401 }
402 }
403
404 public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
405 String servletContextName = null;
406
407 try {
408 ServletContext ctx = event.getServletContext();
409
410 servletContextName = ctx.getServletContextName();
411
412 if (_log.isDebugEnabled()) {
413 _log.debug("Invoking undeploy for " + servletContextName);
414 }
415
416 ObjectValuePair ovp =
417 (ObjectValuePair)_vars.remove(servletContextName);
418
419 if (ovp == null) {
420 return;
421 }
422
423 long[] companyIds = (long[])ovp.getKey();
424 List portlets = (List)ovp.getValue();
425
426 Set portletIds = new HashSet();
427
428 if (portlets != null) {
429 if (_log.isInfoEnabled()) {
430 _log.info(
431 "Unregistering portlets for " + servletContextName);
432 }
433
434 Iterator itr = portlets.iterator();
435
436 while (itr.hasNext()) {
437 Portlet portlet = (Portlet)itr.next();
438
439 SMTPServerUtil.deleteListener(
440 portlet.getSmtpMessageListenerInstance());
441
442 PortletInstanceFactory.destroy(portlet);
443
444 portletIds.add(portlet.getPortletId());
445 }
446 }
447
448 if (portletIds.size() > 0) {
449 for (int i = 0; i < companyIds.length; i++) {
450 long companyId = companyIds[i];
451
452 PortletCategory portletCategory =
453 (PortletCategory)WebAppPool.get(
454 String.valueOf(companyId),
455 WebKeys.PORTLET_CATEGORY);
456
457 portletCategory.separate(portletIds);
458 }
459 }
460
461 PortletResourceBundles.remove(servletContextName);
462
463 if (_log.isInfoEnabled()) {
464 _log.info(
465 "Portlets for " + servletContextName +
466 " unregistered successfully");
467 }
468 }
469 catch (Exception e) {
470 throw new HotDeployException(
471 "Error unregistering portlets for " + servletContextName, e);
472 }
473 }
474
475 protected void processProperties(
476 String servletContextName, ClassLoader portletClassLoader,
477 Properties portletProps)
478 throws Exception {
479
480 String languageBundleName = portletProps.getProperty("language.bundle");
481
482 if (Validator.isNotNull(languageBundleName)) {
483 Locale[] locales = LanguageUtil.getAvailableLocales();
484
485 for (int i = 0; i < locales.length; i++) {
486 ResourceBundle bundle = ResourceBundle.getBundle(
487 languageBundleName, locales[i], portletClassLoader);
488
489 PortletResourceBundles.put(
490 servletContextName, LocaleUtil.toLanguageId(locales[i]),
491 bundle);
492 }
493 }
494
495 String[] resourceActionConfigs = StringUtil.split(
496 portletProps.getProperty("resource.actions.configs"));
497
498 for (int i = 0; i < resourceActionConfigs.length; i++) {
499 ResourceActionsUtil.read(
500 servletContextName, portletClassLoader,
501 resourceActionConfigs[i]);
502 }
503 }
504
505 protected void processServiceBuilder(
506 ServletContext ctx, ClassLoader portletClassLoader)
507 throws Exception {
508
509 if (portletClassLoader.getResourceAsStream(
510 "portlet-service.properties") == null) {
511
512 return;
513 }
514
515 Properties serviceBuilderProps = new Properties();
516
517 PropertiesUtil.load(
518 serviceBuilderProps,
519 StringUtil.read(portletClassLoader, "portlet-service.properties"));
520
521 String buildNamespace = GetterUtil.getString(
522 serviceBuilderProps.getProperty("build.namespace"));
523 long buildNumber = GetterUtil.getLong(
524 serviceBuilderProps.getProperty("build.number"));
525 long buildDate = GetterUtil.getLong(
526 serviceBuilderProps.getProperty("build.date"));
527
528 if (_log.isDebugEnabled()) {
529 _log.debug("Build namespace " + buildNamespace);
530 _log.debug("Build number " + buildNumber);
531 _log.debug("Build date " + buildDate);
532 }
533
534 ServiceComponentLocalServiceUtil.updateServiceComponent(
535 ctx, portletClassLoader, buildNamespace, buildNumber, buildDate);
536 }
537
538 private static Log _log = LogFactory.getLog(PortletHotDeployListener.class);
539
540 private static Map _vars = CollectionFactory.getHashMap();
541
542 }