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