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