1
22
23 package com.liferay.portal.deploy.hot;
24
25 import com.liferay.portal.apache.bridges.struts.LiferayServletContextProvider;
26 import com.liferay.portal.kernel.configuration.Configuration;
27 import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
28 import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
29 import com.liferay.portal.kernel.deploy.hot.HotDeployException;
30 import com.liferay.portal.kernel.job.Scheduler;
31 import com.liferay.portal.kernel.language.LanguageUtil;
32 import com.liferay.portal.kernel.lar.PortletDataHandler;
33 import com.liferay.portal.kernel.pop.MessageListener;
34 import com.liferay.portal.kernel.portlet.ConfigurationAction;
35 import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
36 import com.liferay.portal.kernel.portlet.PortletLayoutListener;
37 import com.liferay.portal.kernel.search.Indexer;
38 import com.liferay.portal.kernel.servlet.PortletServlet;
39 import com.liferay.portal.kernel.servlet.ServletContextProvider;
40 import com.liferay.portal.kernel.servlet.URLEncoder;
41 import com.liferay.portal.kernel.util.ClassUtil;
42 import com.liferay.portal.kernel.util.GetterUtil;
43 import com.liferay.portal.kernel.util.HttpUtil;
44 import com.liferay.portal.kernel.util.LocaleUtil;
45 import com.liferay.portal.kernel.util.ObjectValuePair;
46 import com.liferay.portal.kernel.util.StringUtil;
47 import com.liferay.portal.kernel.util.Validator;
48 import com.liferay.portal.model.Portlet;
49 import com.liferay.portal.model.PortletApp;
50 import com.liferay.portal.model.PortletCategory;
51 import com.liferay.portal.model.PortletFilter;
52 import com.liferay.portal.model.PortletURLListener;
53 import com.liferay.portal.pop.POPServerUtil;
54 import com.liferay.portal.security.permission.ResourceActionsUtil;
55 import com.liferay.portal.service.PortletLocalServiceUtil;
56 import com.liferay.portal.util.Portal;
57 import com.liferay.portal.util.PortalInstances;
58 import com.liferay.portal.util.PropsValues;
59 import com.liferay.portal.util.WebAppPool;
60 import com.liferay.portal.util.WebKeys;
61 import com.liferay.portlet.CustomUserAttributes;
62 import com.liferay.portlet.PortletBag;
63 import com.liferay.portlet.PortletBagPool;
64 import com.liferay.portlet.PortletConfigFactory;
65 import com.liferay.portlet.PortletContextBag;
66 import com.liferay.portlet.PortletContextBagPool;
67 import com.liferay.portlet.PortletFilterFactory;
68 import com.liferay.portlet.PortletInstanceFactory;
69 import com.liferay.portlet.PortletPreferencesSerializer;
70 import com.liferay.portlet.PortletResourceBundles;
71 import com.liferay.portlet.PortletURLListenerFactory;
72 import com.liferay.portlet.social.model.SocialActivityInterpreter;
73 import com.liferay.portlet.social.model.SocialRequestInterpreter;
74 import com.liferay.portlet.social.model.impl.SocialActivityInterpreterImpl;
75 import com.liferay.portlet.social.model.impl.SocialRequestInterpreterImpl;
76 import com.liferay.portlet.social.service.SocialActivityInterpreterLocalServiceUtil;
77 import com.liferay.portlet.social.service.SocialRequestInterpreterLocalServiceUtil;
78
79 import java.util.HashMap;
80 import java.util.HashSet;
81 import java.util.Iterator;
82 import java.util.List;
83 import java.util.Locale;
84 import java.util.Map;
85 import java.util.MissingResourceException;
86 import java.util.Properties;
87 import java.util.ResourceBundle;
88 import java.util.Set;
89
90 import javax.portlet.PortletConfig;
91 import javax.portlet.PortletContext;
92 import javax.portlet.PortletURLGenerationListener;
93 import javax.portlet.PreferencesValidator;
94
95 import javax.servlet.ServletContext;
96
97 import org.apache.commons.logging.Log;
98 import org.apache.commons.logging.LogFactory;
99 import org.apache.portals.bridges.struts.StrutsPortlet;
100
101
109 public class PortletHotDeployListener extends BaseHotDeployListener {
110
111 public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
112 try {
113 doInvokeDeploy(event);
114 }
115 catch (Exception e) {
116 throwHotDeployException(
117 event, "Error registering portlets for ", e);
118 }
119 }
120
121 public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
122 try {
123 doInvokeUndeploy(event);
124 }
125 catch (Exception e) {
126 throwHotDeployException(
127 event, "Error unregistering portlets for ", e);
128 }
129 }
130
131 protected void destroyPortlet(Portlet portlet, Set<String> portletIds)
132 throws Exception {
133
134 PortletApp portletApp = portlet.getPortletApp();
135
136 Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
137
138 for (PortletFilter portletFilter : portletFilters) {
139 PortletFilterFactory.destroy(portletFilter);
140 }
141
142 Set<PortletURLListener> portletURLListeners =
143 portletApp.getPortletURLListeners();
144
145 for (PortletURLListener portletURLListener : portletURLListeners) {
146 PortletURLListenerFactory.destroy(portletURLListener);
147 }
148
149 Scheduler scheduler = portlet.getSchedulerInstance();
150
151 if (scheduler != null) {
152 scheduler.unschedule();
153 }
154
155 POPServerUtil.deleteListener(portlet.getPopMessageListenerInstance());
156
157 SocialActivityInterpreterLocalServiceUtil.deleteActivityInterpreter(
158 portlet.getSocialActivityInterpreterInstance());
159
160 SocialRequestInterpreterLocalServiceUtil.deleteRequestInterpreter(
161 portlet.getSocialRequestInterpreterInstance());
162
163 PortletInstanceFactory.destroy(portlet);
164
165 portletIds.add(portlet.getPortletId());
166 }
167
168 protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
169
170
172 ServletContext servletContext = event.getServletContext();
173
174 String servletContextName = servletContext.getServletContextName();
175
176 if (_log.isDebugEnabled()) {
177 _log.debug("Invoking deploy for " + servletContextName);
178 }
179
180
182 long[] companyIds = PortalInstances.getCompanyIds();
183
184
186 String[] xmls = new String[] {
187 HttpUtil.URLtoString(servletContext.getResource(
188 "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_STANDARD)),
189 HttpUtil.URLtoString(servletContext.getResource(
190 "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_CUSTOM)),
191 HttpUtil.URLtoString(servletContext.getResource(
192 "/WEB-INF/liferay-portlet.xml")),
193 HttpUtil.URLtoString(servletContext.getResource("/WEB-INF/web.xml"))
194 };
195
196 if (xmls[0] == null) {
197 return;
198 }
199
200 if (_log.isInfoEnabled()) {
201 _log.info("Registering portlets for " + servletContextName);
202 }
203
204 List<Portlet> portlets = PortletLocalServiceUtil.initWAR(
205 servletContextName, xmls, event.getPluginPackage());
206
207 if (_log.isInfoEnabled()) {
208 _log.info(
209 portlets.size() + " portlets for " + servletContextName +
210 " are ready for registration");
211 }
212
213
215 ClassLoader portletClassLoader = event.getContextClassLoader();
216
217 servletContext.setAttribute(
218 PortletServlet.PORTLET_CLASS_LOADER, portletClassLoader);
219
220
222 _strutsBridges = false;
223
224 Iterator<Portlet> portletsItr = portlets.iterator();
225
226 while (portletsItr.hasNext()) {
227 Portlet portlet = portletsItr.next();
228
229 initPortlet(
230 portlet, servletContext, portletClassLoader, portletsItr);
231 }
232
233
235 if (!_strutsBridges) {
236 _strutsBridges = GetterUtil.getBoolean(
237 servletContext.getInitParameter(
238 "struts-bridges-context-provider"));
239 }
240
241 if (_strutsBridges) {
242 servletContext.setAttribute(
243 ServletContextProvider.STRUTS_BRIDGES_CONTEXT_PROVIDER,
244 new LiferayServletContextProvider());
245 }
246
247
249 String xml = HttpUtil.URLtoString(servletContext.getResource(
250 "/WEB-INF/liferay-display.xml"));
251
252 PortletCategory newPortletCategory =
253 PortletLocalServiceUtil.getWARDisplay(servletContextName, xml);
254
255 for (int i = 0; i < companyIds.length; i++) {
256 long companyId = companyIds[i];
257
258 PortletCategory portletCategory =
259 (PortletCategory)WebAppPool.get(
260 String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
261
262 if (portletCategory != null) {
263 portletCategory.merge(newPortletCategory);
264 }
265 else {
266 _log.error(
267 "Unable to register portlet for company " + companyId +
268 " because it does not exist");
269 }
270 }
271
272
274 processPortletProperties(servletContextName, portletClassLoader);
275
276
278 _vars.put(
279 servletContextName,
280 new ObjectValuePair<long[], List<Portlet>>(
281 companyIds, portlets));
282
283 if (_log.isInfoEnabled()) {
284 _log.info(
285 portlets.size() + " portlets for " + servletContextName +
286 " registered successfully");
287 }
288 }
289
290 protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
291 ServletContext servletContext = event.getServletContext();
292
293 String servletContextName = servletContext.getServletContextName();
294
295 if (_log.isDebugEnabled()) {
296 _log.debug("Invoking undeploy for " + servletContextName);
297 }
298
299 ObjectValuePair<long[], List<Portlet>> ovp =
300 _vars.remove(servletContextName);
301
302 if (ovp == null) {
303 return;
304 }
305
306 long[] companyIds = ovp.getKey();
307 List<Portlet> portlets = ovp.getValue();
308
309 Set<String> portletIds = new HashSet<String>();
310
311 if (portlets != null) {
312 if (_log.isInfoEnabled()) {
313 _log.info(
314 "Unregistering portlets for " + servletContextName);
315 }
316
317 Iterator<Portlet> itr = portlets.iterator();
318
319 while (itr.hasNext()) {
320 Portlet portlet = itr.next();
321
322 destroyPortlet(portlet, portletIds);
323 }
324 }
325
326 if (portletIds.size() > 0) {
327 for (int i = 0; i < companyIds.length; i++) {
328 long companyId = companyIds[i];
329
330 PortletCategory portletCategory =
331 (PortletCategory)WebAppPool.get(
332 String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
333
334 portletCategory.separate(portletIds);
335 }
336 }
337
338 PortletResourceBundles.remove(servletContextName);
339
340 if (_log.isInfoEnabled()) {
341 _log.info(
342 portlets.size() + " portlets for " + servletContextName +
343 " unregistered successfully");
344 }
345 }
346
347 protected void initPortlet(
348 Portlet portlet, ServletContext servletContext,
349 ClassLoader portletClassLoader, Iterator<Portlet> portletsItr)
350 throws Exception {
351
352 Class<?> portletClass = null;
353
354 try {
355 portletClass = portletClassLoader.loadClass(
356 portlet.getPortletClass());
357 }
358 catch (Exception e) {
359 _log.error(e, e);
360
361 portletsItr.remove();
362
363 PortletLocalServiceUtil.destroyPortlet(portlet);
364
365 return;
366 }
367
368 javax.portlet.Portlet portletInstance =
369 (javax.portlet.Portlet)portletClass.newInstance();
370
371 if (ClassUtil.isSubclass(portletClass, StrutsPortlet.class.getName())) {
372 _strutsBridges = true;
373 }
374
375 ConfigurationAction configurationActionInstance = null;
376
377 if (Validator.isNotNull(portlet.getConfigurationActionClass())) {
378 configurationActionInstance =
379 (ConfigurationAction)portletClassLoader.loadClass(
380 portlet.getConfigurationActionClass()).newInstance();
381 }
382
383 Indexer indexerInstance = null;
384
385 if (Validator.isNotNull(portlet.getIndexerClass())) {
386 indexerInstance = (Indexer)portletClassLoader.loadClass(
387 portlet.getIndexerClass()).newInstance();
388 }
389
390 Scheduler schedulerInstance = null;
391
392 if (PropsValues.SCHEDULER_ENABLED &&
393 Validator.isNotNull(portlet.getSchedulerClass())) {
394
395 schedulerInstance = (Scheduler)portletClassLoader.loadClass(
396 portlet.getSchedulerClass()).newInstance();
397
398 schedulerInstance.schedule();
399 }
400
401 FriendlyURLMapper friendlyURLMapperInstance = null;
402
403 if (Validator.isNotNull(portlet.getFriendlyURLMapperClass())) {
404 friendlyURLMapperInstance =
405 (FriendlyURLMapper)portletClassLoader.loadClass(
406 portlet.getFriendlyURLMapperClass()).newInstance();
407 }
408
409 URLEncoder urlEncoderInstance = null;
410
411 if (Validator.isNotNull(portlet.getURLEncoderClass())) {
412 urlEncoderInstance = (URLEncoder)portletClassLoader.loadClass(
413 portlet.getURLEncoderClass()).newInstance();
414 }
415
416 PortletDataHandler portletDataHandlerInstance = null;
417
418 if (Validator.isNotNull(portlet.getPortletDataHandlerClass())) {
419 portletDataHandlerInstance =
420 (PortletDataHandler)portletClassLoader.loadClass(
421 portlet.getPortletDataHandlerClass()).newInstance();
422 }
423
424 PortletLayoutListener portletLayoutListenerInstance = null;
425
426 if (Validator.isNotNull(portlet.getPortletLayoutListenerClass())) {
427 portletLayoutListenerInstance =
428 (PortletLayoutListener)portletClassLoader.loadClass(
429 portlet.getPortletLayoutListenerClass()).newInstance();
430 }
431
432 MessageListener popMessageListenerInstance = null;
433
434 if (Validator.isNotNull(portlet.getPopMessageListenerClass())) {
435 popMessageListenerInstance =
436 (MessageListener)portletClassLoader.loadClass(
437 portlet.getPopMessageListenerClass()).newInstance();
438
439 POPServerUtil.addListener(popMessageListenerInstance);
440 }
441
442 SocialActivityInterpreter socialActivityInterpreterInstance = null;
443
444 if (Validator.isNotNull(portlet.getSocialActivityInterpreterClass())) {
445 socialActivityInterpreterInstance =
446 (SocialActivityInterpreter)portletClassLoader.loadClass(
447 portlet.getSocialActivityInterpreterClass()).newInstance();
448
449 socialActivityInterpreterInstance =
450 new SocialActivityInterpreterImpl(
451 portlet.getPortletId(), socialActivityInterpreterInstance);
452
453 SocialActivityInterpreterLocalServiceUtil.addActivityInterpreter(
454 socialActivityInterpreterInstance);
455 }
456
457 SocialRequestInterpreter socialRequestInterpreterInstance = null;
458
459 if (Validator.isNotNull(portlet.getSocialRequestInterpreterClass())) {
460 socialRequestInterpreterInstance =
461 (SocialRequestInterpreter)portletClassLoader.loadClass(
462 portlet.getSocialRequestInterpreterClass()).newInstance();
463
464 socialRequestInterpreterInstance = new SocialRequestInterpreterImpl(
465 portlet.getPortletId(), socialRequestInterpreterInstance);
466
467 SocialRequestInterpreterLocalServiceUtil.addRequestInterpreter(
468 socialRequestInterpreterInstance);
469 }
470
471 PreferencesValidator prefsValidatorInstance = null;
472
473 if (Validator.isNotNull(portlet.getPreferencesValidator())) {
474 prefsValidatorInstance =
475 (PreferencesValidator)portletClassLoader.loadClass(
476 portlet.getPreferencesValidator()).newInstance();
477
478 try {
479 if (PropsValues.PREFERENCE_VALIDATE_ON_STARTUP) {
480 prefsValidatorInstance.validate(
481 PortletPreferencesSerializer.fromDefaultXML(
482 portlet.getDefaultPreferences()));
483 }
484 }
485 catch (Exception e) {
486 _log.warn(
487 "Portlet with the name " + portlet.getPortletId() +
488 " does not have valid default preferences");
489 }
490 }
491
492 Map<String, ResourceBundle> resourceBundles = null;
493
494 if (Validator.isNotNull(portlet.getResourceBundle())) {
495 resourceBundles = new HashMap<String, ResourceBundle>();
496
497 initResourceBundle(
498 resourceBundles, portlet, portletClassLoader,
499 LocaleUtil.getDefault());
500
501 Iterator<String> supportLocalesItr =
502 portlet.getSupportedLocales().iterator();
503
504 while (supportLocalesItr.hasNext()) {
505 String supportedLocale = supportLocalesItr.next();
506
507 Locale locale = LocaleUtil.fromLanguageId(supportedLocale);
508
509 initResourceBundle(
510 resourceBundles, portlet, portletClassLoader, locale);
511 }
512 }
513
514 PortletBag portletBag = new PortletBag(
515 portlet.getPortletId(), servletContext, portletInstance,
516 configurationActionInstance, indexerInstance, schedulerInstance,
517 friendlyURLMapperInstance, urlEncoderInstance,
518 portletDataHandlerInstance, portletLayoutListenerInstance,
519 popMessageListenerInstance, socialActivityInterpreterInstance,
520 socialRequestInterpreterInstance, prefsValidatorInstance,
521 resourceBundles);
522
523 PortletBagPool.put(portlet.getPortletId(), portletBag);
524
525 if (!portletsItr.hasNext()) {
526 initPortletApp(portlet, servletContext, portletClassLoader);
527 }
528
529 try {
530 PortletInstanceFactory.create(portlet, servletContext);
531 }
532 catch (Exception e) {
533 _log.error(e, e);
534 }
535 }
536
537 protected void initPortletApp(
538 Portlet portlet, ServletContext servletContext,
539 ClassLoader portletClassLoader)
540 throws Exception {
541
542 String servletContextName = servletContext.getServletContextName();
543
544 PortletConfig portletConfig = PortletConfigFactory.create(
545 portlet, servletContext);
546
547 PortletContext portletContext = portletConfig.getPortletContext();
548
549 PortletContextBag portletContextBag = new PortletContextBag(
550 servletContextName);
551
552 PortletContextBagPool.put(servletContextName, portletContextBag);
553
554 PortletApp portletApp = portlet.getPortletApp();
555
556 Map<String, String> customUserAttributes =
557 portletApp.getCustomUserAttributes();
558
559 for (Map.Entry<String, String> entry :
560 customUserAttributes.entrySet()) {
561
562 String attrCustomClass = entry.getValue();
563
564 CustomUserAttributes customUserAttributesInstance =
565 (CustomUserAttributes)portletClassLoader.loadClass(
566 attrCustomClass).newInstance();
567
568 portletContextBag.getCustomUserAttributes().put(
569 attrCustomClass, customUserAttributesInstance);
570 }
571
572 Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
573
574 for (PortletFilter portletFilter : portletFilters) {
575 javax.portlet.filter.PortletFilter portletFilterInstance =
576 (javax.portlet.filter.PortletFilter)
577 portletClassLoader.loadClass(
578 portletFilter.getFilterClass()).newInstance();
579
580 portletContextBag.getPortletFilters().put(
581 portletFilter.getFilterName(), portletFilterInstance);
582
583 PortletFilterFactory.create(portletFilter, portletContext);
584 }
585
586 Set<PortletURLListener> portletURLListeners =
587 portletApp.getPortletURLListeners();
588
589 for (PortletURLListener portletURLListener : portletURLListeners) {
590 PortletURLGenerationListener portletURLListenerInstance =
591 (PortletURLGenerationListener)portletClassLoader.loadClass(
592 portletURLListener.getListenerClass()).newInstance();
593
594 portletContextBag.getPortletURLListeners().put(
595 portletURLListener.getListenerClass(),
596 portletURLListenerInstance);
597
598 PortletURLListenerFactory.create(portletURLListener);
599 }
600 }
601
602 protected void initResourceBundle(
603 Map<String, ResourceBundle> resourceBundles, Portlet portlet,
604 ClassLoader portletClassLoader, Locale locale) {
605
606 try {
607 ResourceBundle resourceBundle = ResourceBundle.getBundle(
608 portlet.getResourceBundle(), locale, portletClassLoader);
609
610 resourceBundles.put(
611 LocaleUtil.toLanguageId(locale), resourceBundle);
612 }
613 catch (MissingResourceException mre) {
614 _log.warn(mre.getMessage());
615 }
616 }
617
618 protected void processPortletProperties(
619 String servletContextName, ClassLoader portletClassLoader)
620 throws Exception {
621
622 Configuration portletPropertiesConfiguration = null;
623
624 try {
625 portletPropertiesConfiguration =
626 ConfigurationFactoryUtil.getConfiguration(
627 portletClassLoader, "portlet");
628 }
629 catch (Exception e) {
630 if (_log.isDebugEnabled()) {
631 _log.debug("Unable to read portlet.properties");
632 }
633 }
634
635 if (portletPropertiesConfiguration == null) {
636 return;
637 }
638
639 Properties portletProperties =
640 portletPropertiesConfiguration.getProperties();
641
642 if (portletProperties.size() == 0) {
643 return;
644 }
645
646 String languageBundleName = portletProperties.getProperty(
647 "language.bundle");
648
649 if (Validator.isNotNull(languageBundleName)) {
650 Locale[] locales = LanguageUtil.getAvailableLocales();
651
652 for (int i = 0; i < locales.length; i++) {
653 ResourceBundle bundle = ResourceBundle.getBundle(
654 languageBundleName, locales[i], portletClassLoader);
655
656 PortletResourceBundles.put(
657 servletContextName, LocaleUtil.toLanguageId(locales[i]),
658 bundle);
659 }
660 }
661
662 String[] resourceActionConfigs = StringUtil.split(
663 portletProperties.getProperty("resource.actions.configs"));
664
665 for (int i = 0; i < resourceActionConfigs.length; i++) {
666 ResourceActionsUtil.read(
667 servletContextName, portletClassLoader,
668 resourceActionConfigs[i]);
669 }
670 }
671
672 private static Log _log = LogFactory.getLog(PortletHotDeployListener.class);
673
674 private static Map<String, ObjectValuePair<long[], List<Portlet>>> _vars =
675 new HashMap<String, ObjectValuePair<long[], List<Portlet>>>();
676
677 private boolean _strutsBridges;
678
679 }