1
19
20 package com.liferay.portal.deploy.hot;
21
22 import com.liferay.portal.apache.bridges.struts.LiferayServletContextProvider;
23 import com.liferay.portal.kernel.configuration.Configuration;
24 import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
25 import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
26 import com.liferay.portal.kernel.deploy.hot.HotDeployException;
27 import com.liferay.portal.kernel.job.Scheduler;
28 import com.liferay.portal.kernel.language.LanguageUtil;
29 import com.liferay.portal.kernel.log.Log;
30 import com.liferay.portal.kernel.log.LogFactoryUtil;
31 import com.liferay.portal.kernel.pop.MessageListener;
32 import com.liferay.portal.kernel.portlet.ConfigurationAction;
33 import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
34 import com.liferay.portal.kernel.portlet.PortletBag;
35 import com.liferay.portal.kernel.portlet.PortletBagPool;
36 import com.liferay.portal.kernel.portlet.PortletLayoutListener;
37 import com.liferay.portal.kernel.search.Indexer;
38 import com.liferay.portal.kernel.search.IndexerWrapper;
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.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 (Throwable t) {
116 throwHotDeployException(
117 event, "Error registering portlets for ", t);
118 }
119 }
120
121 public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
122 try {
123 doInvokeUndeploy(event);
124 }
125 catch (Throwable t) {
126 throwHotDeployException(
127 event, "Error unregistering portlets for ", t);
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, servletContext, xmls, event.getPluginPackage());
206
207
209 ClassLoader portletClassLoader = event.getContextClassLoader();
210
211 servletContext.setAttribute(
212 PortletServlet.PORTLET_CLASS_LOADER, portletClassLoader);
213
214
216 _portletAppInitialized = false;
217 _strutsBridges = false;
218
219 Iterator<Portlet> portletsItr = portlets.iterator();
220
221 while (portletsItr.hasNext()) {
222 Portlet portlet = portletsItr.next();
223
224 initPortlet(
225 portlet, servletContext, portletClassLoader, portletsItr);
226 }
227
228
230 if (!_strutsBridges) {
231 _strutsBridges = GetterUtil.getBoolean(
232 servletContext.getInitParameter(
233 "struts-bridges-context-provider"));
234 }
235
236 if (_strutsBridges) {
237 servletContext.setAttribute(
238 ServletContextProvider.STRUTS_BRIDGES_CONTEXT_PROVIDER,
239 new LiferayServletContextProvider());
240 }
241
242
244 String xml = HttpUtil.URLtoString(servletContext.getResource(
245 "/WEB-INF/liferay-display.xml"));
246
247 PortletCategory newPortletCategory =
248 PortletLocalServiceUtil.getWARDisplay(servletContextName, xml);
249
250 for (int i = 0; i < companyIds.length; i++) {
251 long companyId = companyIds[i];
252
253 PortletCategory portletCategory =
254 (PortletCategory)WebAppPool.get(
255 String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
256
257 if (portletCategory != null) {
258 portletCategory.merge(newPortletCategory);
259 }
260 else {
261 _log.error(
262 "Unable to register portlet for company " + companyId +
263 " because it does not exist");
264 }
265 }
266
267
269 processPortletProperties(servletContextName, portletClassLoader);
270
271
273 _vars.put(
274 servletContextName,
275 new ObjectValuePair<long[], List<Portlet>>(
276 companyIds, portlets));
277
278 if (_log.isInfoEnabled()) {
279 if (portlets.size() == 1) {
280 _log.info(
281 "1 portlet for " + servletContextName +
282 " is available for use");
283 }
284 else {
285 _log.info(
286 portlets.size() + " portlets for " + servletContextName +
287 " are available for use");
288 }
289 }
290 }
291
292 protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
293 ServletContext servletContext = event.getServletContext();
294
295 String servletContextName = servletContext.getServletContextName();
296
297 if (_log.isDebugEnabled()) {
298 _log.debug("Invoking undeploy for " + servletContextName);
299 }
300
301 ObjectValuePair<long[], List<Portlet>> ovp =
302 _vars.remove(servletContextName);
303
304 if (ovp == null) {
305 return;
306 }
307
308 long[] companyIds = ovp.getKey();
309 List<Portlet> portlets = ovp.getValue();
310
311 Set<String> portletIds = new HashSet<String>();
312
313 if (portlets != null) {
314 if (_log.isInfoEnabled()) {
315 _log.info(
316 "Unregistering portlets for " + servletContextName);
317 }
318
319 Iterator<Portlet> itr = portlets.iterator();
320
321 while (itr.hasNext()) {
322 Portlet portlet = itr.next();
323
324 destroyPortlet(portlet, portletIds);
325 }
326 }
327
328 if (portletIds.size() > 0) {
329 for (int i = 0; i < companyIds.length; i++) {
330 long companyId = companyIds[i];
331
332 PortletCategory portletCategory =
333 (PortletCategory)WebAppPool.get(
334 String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
335
336 portletCategory.separate(portletIds);
337 }
338 }
339
340 PortletResourceBundles.remove(servletContextName);
341
342 if (_log.isInfoEnabled()) {
343 if (portlets.size() == 1) {
344 _log.info(
345 "1 portlet for " + servletContextName +
346 " was unregistered");
347 }
348 else {
349 _log.info(
350 portlets.size() + " portlets for " + servletContextName +
351 " was unregistered");
352 }
353 }
354 }
355
356 protected void initPortlet(
357 Portlet portlet, ServletContext servletContext,
358 ClassLoader portletClassLoader, Iterator<Portlet> portletsItr)
359 throws Exception {
360
361 Class<?> portletClass = null;
362
363 try {
364 portletClass = portletClassLoader.loadClass(
365 portlet.getPortletClass());
366 }
367 catch (Exception e) {
368 _log.error(e, e);
369
370 portletsItr.remove();
371
372 PortletLocalServiceUtil.destroyPortlet(portlet);
373
374 return;
375 }
376
377 javax.portlet.Portlet portletInstance =
378 (javax.portlet.Portlet)portletClass.newInstance();
379
380 if (ClassUtil.isSubclass(portletClass, StrutsPortlet.class.getName())) {
381 _strutsBridges = true;
382 }
383
384 ConfigurationAction configurationActionInstance = null;
385
386 if (Validator.isNotNull(portlet.getConfigurationActionClass())) {
387 configurationActionInstance =
388 (ConfigurationAction)portletClassLoader.loadClass(
389 portlet.getConfigurationActionClass()).newInstance();
390 }
391
392 Indexer indexerInstance = null;
393
394 if (Validator.isNotNull(portlet.getIndexerClass())) {
395 indexerInstance = (Indexer)portletClassLoader.loadClass(
396 portlet.getIndexerClass()).newInstance();
397
398 indexerInstance = new IndexerWrapper(
399 indexerInstance, portletClassLoader);
400 }
401
402 OpenSearch openSearchInstance = null;
403
404 if (Validator.isNotNull(portlet.getOpenSearchClass())) {
405 openSearchInstance = (OpenSearch)portletClassLoader.loadClass(
406 portlet.getOpenSearchClass()).newInstance();
407 }
408
409 Scheduler schedulerInstance = null;
410
411 if (PropsValues.SCHEDULER_ENABLED &&
412 Validator.isNotNull(portlet.getSchedulerClass())) {
413
414 schedulerInstance = (Scheduler)portletClassLoader.loadClass(
415 portlet.getSchedulerClass()).newInstance();
416
417 schedulerInstance.schedule();
418 }
419
420 FriendlyURLMapper friendlyURLMapperInstance = null;
421
422 if (Validator.isNotNull(portlet.getFriendlyURLMapperClass())) {
423 friendlyURLMapperInstance =
424 (FriendlyURLMapper)portletClassLoader.loadClass(
425 portlet.getFriendlyURLMapperClass()).newInstance();
426 }
427
428 URLEncoder urlEncoderInstance = null;
429
430 if (Validator.isNotNull(portlet.getURLEncoderClass())) {
431 urlEncoderInstance = (URLEncoder)portletClassLoader.loadClass(
432 portlet.getURLEncoderClass()).newInstance();
433 }
434
435 PortletDataHandler portletDataHandlerInstance = null;
436
437 if (Validator.isNotNull(portlet.getPortletDataHandlerClass())) {
438 portletDataHandlerInstance =
439 (PortletDataHandler)portletClassLoader.loadClass(
440 portlet.getPortletDataHandlerClass()).newInstance();
441 }
442
443 PortletLayoutListener portletLayoutListenerInstance = null;
444
445 if (Validator.isNotNull(portlet.getPortletLayoutListenerClass())) {
446 portletLayoutListenerInstance =
447 (PortletLayoutListener)portletClassLoader.loadClass(
448 portlet.getPortletLayoutListenerClass()).newInstance();
449 }
450
451 MessageListener popMessageListenerInstance = null;
452
453 if (Validator.isNotNull(portlet.getPopMessageListenerClass())) {
454 popMessageListenerInstance =
455 (MessageListener)portletClassLoader.loadClass(
456 portlet.getPopMessageListenerClass()).newInstance();
457
458 POPServerUtil.addListener(popMessageListenerInstance);
459 }
460
461 SocialActivityInterpreter socialActivityInterpreterInstance = null;
462
463 if (Validator.isNotNull(portlet.getSocialActivityInterpreterClass())) {
464 socialActivityInterpreterInstance =
465 (SocialActivityInterpreter)portletClassLoader.loadClass(
466 portlet.getSocialActivityInterpreterClass()).newInstance();
467
468 socialActivityInterpreterInstance =
469 new SocialActivityInterpreterImpl(
470 portlet.getPortletId(), socialActivityInterpreterInstance);
471
472 SocialActivityInterpreterLocalServiceUtil.addActivityInterpreter(
473 socialActivityInterpreterInstance);
474 }
475
476 SocialRequestInterpreter socialRequestInterpreterInstance = null;
477
478 if (Validator.isNotNull(portlet.getSocialRequestInterpreterClass())) {
479 socialRequestInterpreterInstance =
480 (SocialRequestInterpreter)portletClassLoader.loadClass(
481 portlet.getSocialRequestInterpreterClass()).newInstance();
482
483 socialRequestInterpreterInstance = new SocialRequestInterpreterImpl(
484 portlet.getPortletId(), socialRequestInterpreterInstance);
485
486 SocialRequestInterpreterLocalServiceUtil.addRequestInterpreter(
487 socialRequestInterpreterInstance);
488 }
489
490 PreferencesValidator prefsValidatorInstance = null;
491
492 if (Validator.isNotNull(portlet.getPreferencesValidator())) {
493 prefsValidatorInstance =
494 (PreferencesValidator)portletClassLoader.loadClass(
495 portlet.getPreferencesValidator()).newInstance();
496
497 try {
498 if (PropsValues.PREFERENCE_VALIDATE_ON_STARTUP) {
499 prefsValidatorInstance.validate(
500 PortletPreferencesSerializer.fromDefaultXML(
501 portlet.getDefaultPreferences()));
502 }
503 }
504 catch (Exception e) {
505 _log.warn(
506 "Portlet with the name " + portlet.getPortletId() +
507 " does not have valid default preferences");
508 }
509 }
510
511 Map<String, ResourceBundle> resourceBundles = null;
512
513 if (Validator.isNotNull(portlet.getResourceBundle())) {
514 resourceBundles = new HashMap<String, ResourceBundle>();
515
516 initResourceBundle(
517 resourceBundles, portlet, portletClassLoader,
518 LocaleUtil.getDefault());
519
520 Iterator<String> supportLocalesItr =
521 portlet.getSupportedLocales().iterator();
522
523 while (supportLocalesItr.hasNext()) {
524 String supportedLocale = supportLocalesItr.next();
525
526 Locale locale = LocaleUtil.fromLanguageId(supportedLocale);
527
528 initResourceBundle(
529 resourceBundles, portlet, portletClassLoader, locale);
530 }
531 }
532
533 PortletBag portletBag = new PortletBagImpl(
534 portlet.getPortletId(), servletContext, portletInstance,
535 configurationActionInstance, indexerInstance, openSearchInstance,
536 schedulerInstance, friendlyURLMapperInstance, urlEncoderInstance,
537 portletDataHandlerInstance, portletLayoutListenerInstance,
538 popMessageListenerInstance, socialActivityInterpreterInstance,
539 socialRequestInterpreterInstance, prefsValidatorInstance,
540 resourceBundles);
541
542 PortletBagPool.put(portlet.getPortletId(), portletBag);
543
544 if (!_portletAppInitialized) {
545 initPortletApp(portlet, servletContext, portletClassLoader);
546
547 _portletAppInitialized = true;
548 }
549
550 try {
551 PortletInstanceFactory.create(portlet, servletContext);
552 }
553 catch (Exception e) {
554 _log.error(e, e);
555 }
556 }
557
558 protected void initPortletApp(
559 Portlet portlet, ServletContext servletContext,
560 ClassLoader portletClassLoader)
561 throws Exception {
562
563 String servletContextName = servletContext.getServletContextName();
564
565 PortletConfig portletConfig = PortletConfigFactory.create(
566 portlet, servletContext);
567
568 PortletContext portletContext = portletConfig.getPortletContext();
569
570 PortletContextBag portletContextBag = new PortletContextBag(
571 servletContextName);
572
573 PortletContextBagPool.put(servletContextName, portletContextBag);
574
575 PortletApp portletApp = portlet.getPortletApp();
576
577 Map<String, String> customUserAttributes =
578 portletApp.getCustomUserAttributes();
579
580 for (Map.Entry<String, String> entry :
581 customUserAttributes.entrySet()) {
582
583 String attrCustomClass = entry.getValue();
584
585 CustomUserAttributes customUserAttributesInstance =
586 (CustomUserAttributes)portletClassLoader.loadClass(
587 attrCustomClass).newInstance();
588
589 portletContextBag.getCustomUserAttributes().put(
590 attrCustomClass, customUserAttributesInstance);
591 }
592
593 Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
594
595 for (PortletFilter portletFilter : portletFilters) {
596 javax.portlet.filter.PortletFilter portletFilterInstance =
597 (javax.portlet.filter.PortletFilter)
598 portletClassLoader.loadClass(
599 portletFilter.getFilterClass()).newInstance();
600
601 portletContextBag.getPortletFilters().put(
602 portletFilter.getFilterName(), portletFilterInstance);
603
604 PortletFilterFactory.create(portletFilter, portletContext);
605 }
606
607 Set<PortletURLListener> portletURLListeners =
608 portletApp.getPortletURLListeners();
609
610 for (PortletURLListener portletURLListener : portletURLListeners) {
611 PortletURLGenerationListener portletURLListenerInstance =
612 (PortletURLGenerationListener)portletClassLoader.loadClass(
613 portletURLListener.getListenerClass()).newInstance();
614
615 portletContextBag.getPortletURLListeners().put(
616 portletURLListener.getListenerClass(),
617 portletURLListenerInstance);
618
619 PortletURLListenerFactory.create(portletURLListener);
620 }
621 }
622
623 protected void initResourceBundle(
624 Map<String, ResourceBundle> resourceBundles, Portlet portlet,
625 ClassLoader portletClassLoader, Locale locale) {
626
627 try {
628 ResourceBundle resourceBundle = ResourceBundle.getBundle(
629 portlet.getResourceBundle(), locale, portletClassLoader);
630
631 resourceBundles.put(
632 LocaleUtil.toLanguageId(locale), resourceBundle);
633 }
634 catch (MissingResourceException mre) {
635 _log.warn(mre.getMessage());
636 }
637 }
638
639 protected void processPortletProperties(
640 String servletContextName, ClassLoader portletClassLoader)
641 throws Exception {
642
643 Configuration portletPropertiesConfiguration = null;
644
645 try {
646 portletPropertiesConfiguration =
647 ConfigurationFactoryUtil.getConfiguration(
648 portletClassLoader, "portlet");
649 }
650 catch (Exception e) {
651 if (_log.isDebugEnabled()) {
652 _log.debug("Unable to read portlet.properties");
653 }
654
655 return;
656 }
657
658 Properties portletProperties =
659 portletPropertiesConfiguration.getProperties();
660
661 if (portletProperties.size() == 0) {
662 return;
663 }
664
665 String languageBundleName = portletProperties.getProperty(
666 "language.bundle");
667
668 if (Validator.isNotNull(languageBundleName)) {
669 Locale[] locales = LanguageUtil.getAvailableLocales();
670
671 for (int i = 0; i < locales.length; i++) {
672 ResourceBundle bundle = ResourceBundle.getBundle(
673 languageBundleName, locales[i], portletClassLoader);
674
675 PortletResourceBundles.put(
676 servletContextName, LocaleUtil.toLanguageId(locales[i]),
677 bundle);
678 }
679 }
680
681 String[] resourceActionConfigs = StringUtil.split(
682 portletProperties.getProperty("resource.actions.configs"));
683
684 for (int i = 0; i < resourceActionConfigs.length; i++) {
685 ResourceActionsUtil.read(
686 servletContextName, portletClassLoader,
687 resourceActionConfigs[i]);
688 }
689 }
690
691 private static Log _log =
692 LogFactoryUtil.getLog(PortletHotDeployListener.class);
693
694 private static Map<String, ObjectValuePair<long[], List<Portlet>>> _vars =
695 new HashMap<String, ObjectValuePair<long[], List<Portlet>>>();
696
697 private boolean _portletAppInitialized;
698 private boolean _strutsBridges;
699
700 }