001
014
015 package com.liferay.portal.deploy.hot;
016
017 import com.liferay.portal.apache.bridges.struts.LiferayServletContextProvider;
018 import com.liferay.portal.kernel.atom.AtomCollectionAdapter;
019 import com.liferay.portal.kernel.atom.AtomCollectionAdapterRegistryUtil;
020 import com.liferay.portal.kernel.configuration.Configuration;
021 import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
022 import com.liferay.portal.kernel.deploy.hot.BaseHotDeployListener;
023 import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
024 import com.liferay.portal.kernel.deploy.hot.HotDeployException;
025 import com.liferay.portal.kernel.javadoc.JavadocManagerUtil;
026 import com.liferay.portal.kernel.language.LanguageUtil;
027 import com.liferay.portal.kernel.lar.StagedModelDataHandler;
028 import com.liferay.portal.kernel.lar.StagedModelDataHandlerRegistryUtil;
029 import com.liferay.portal.kernel.log.Log;
030 import com.liferay.portal.kernel.log.LogFactoryUtil;
031 import com.liferay.portal.kernel.notifications.UserNotificationHandler;
032 import com.liferay.portal.kernel.notifications.UserNotificationManagerUtil;
033 import com.liferay.portal.kernel.portlet.PortletBag;
034 import com.liferay.portal.kernel.scheduler.SchedulerEngineHelperUtil;
035 import com.liferay.portal.kernel.scheduler.SchedulerEntry;
036 import com.liferay.portal.kernel.scheduler.StorageType;
037 import com.liferay.portal.kernel.search.Indexer;
038 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
039 import com.liferay.portal.kernel.servlet.DirectServletRegistryUtil;
040 import com.liferay.portal.kernel.servlet.PortletServlet;
041 import com.liferay.portal.kernel.servlet.ServletContextPool;
042 import com.liferay.portal.kernel.servlet.ServletContextProvider;
043 import com.liferay.portal.kernel.trash.TrashHandler;
044 import com.liferay.portal.kernel.trash.TrashHandlerRegistryUtil;
045 import com.liferay.portal.kernel.util.ClassUtil;
046 import com.liferay.portal.kernel.util.GetterUtil;
047 import com.liferay.portal.kernel.util.HttpUtil;
048 import com.liferay.portal.kernel.util.InfrastructureUtil;
049 import com.liferay.portal.kernel.util.LocaleUtil;
050 import com.liferay.portal.kernel.util.PropsKeys;
051 import com.liferay.portal.kernel.util.ServerDetector;
052 import com.liferay.portal.kernel.util.StringUtil;
053 import com.liferay.portal.kernel.util.Validator;
054 import com.liferay.portal.kernel.webdav.WebDAVUtil;
055 import com.liferay.portal.kernel.workflow.WorkflowHandler;
056 import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
057 import com.liferay.portal.model.Portlet;
058 import com.liferay.portal.model.PortletApp;
059 import com.liferay.portal.model.PortletCategory;
060 import com.liferay.portal.model.PortletFilter;
061 import com.liferay.portal.model.PortletURLListener;
062 import com.liferay.portal.poller.PollerProcessorUtil;
063 import com.liferay.portal.pop.POPServerUtil;
064 import com.liferay.portal.security.permission.ResourceActionsUtil;
065 import com.liferay.portal.service.PortletLocalServiceUtil;
066 import com.liferay.portal.service.ResourceActionLocalServiceUtil;
067 import com.liferay.portal.util.Portal;
068 import com.liferay.portal.util.PortalInstances;
069 import com.liferay.portal.util.PropsValues;
070 import com.liferay.portal.util.WebAppPool;
071 import com.liferay.portal.util.WebKeys;
072 import com.liferay.portal.xmlrpc.XmlRpcServlet;
073 import com.liferay.portlet.CustomUserAttributes;
074 import com.liferay.portlet.InvokerPortlet;
075 import com.liferay.portlet.PortletBagFactory;
076 import com.liferay.portlet.PortletContextBag;
077 import com.liferay.portlet.PortletContextBagPool;
078 import com.liferay.portlet.PortletFilterFactory;
079 import com.liferay.portlet.PortletInstanceFactoryUtil;
080 import com.liferay.portlet.PortletResourceBundles;
081 import com.liferay.portlet.PortletURLListenerFactory;
082 import com.liferay.portlet.asset.AssetRendererFactoryRegistryUtil;
083 import com.liferay.portlet.asset.model.AssetRendererFactory;
084 import com.liferay.portlet.social.model.SocialActivityInterpreter;
085 import com.liferay.portlet.social.service.SocialActivityInterpreterLocalServiceUtil;
086 import com.liferay.portlet.social.service.SocialRequestInterpreterLocalServiceUtil;
087 import com.liferay.util.bridges.php.PHPPortlet;
088
089 import java.util.HashMap;
090 import java.util.HashSet;
091 import java.util.Iterator;
092 import java.util.List;
093 import java.util.Locale;
094 import java.util.Map;
095 import java.util.Properties;
096 import java.util.ResourceBundle;
097 import java.util.Set;
098
099 import javax.naming.Context;
100 import javax.naming.InitialContext;
101 import javax.naming.NamingException;
102
103 import javax.portlet.PortletURLGenerationListener;
104
105 import javax.servlet.ServletContext;
106
107 import javax.sql.DataSource;
108
109 import org.apache.portals.bridges.struts.StrutsPortlet;
110
111
117 public class PortletHotDeployListener extends BaseHotDeployListener {
118
119 @Override
120 public void invokeDeploy(HotDeployEvent hotDeployEvent)
121 throws HotDeployException {
122
123 try {
124 doInvokeDeploy(hotDeployEvent);
125 }
126 catch (Throwable t) {
127 throwHotDeployException(
128 hotDeployEvent,
129 "Error registering portlets for " +
130 hotDeployEvent.getServletContextName(),
131 t);
132 }
133 }
134
135 @Override
136 public void invokeUndeploy(HotDeployEvent hotDeployEvent)
137 throws HotDeployException {
138
139 try {
140 doInvokeUndeploy(hotDeployEvent);
141 }
142 catch (Throwable t) {
143 throwHotDeployException(
144 hotDeployEvent,
145 "Error unregistering portlets for " +
146 hotDeployEvent.getServletContextName(),
147 t);
148 }
149 }
150
151 protected void bindDataSource(String servletContextName) throws Exception {
152 if (ServerDetector.isGlassfish() || ServerDetector.isJOnAS()) {
153 return;
154 }
155
156 if (_log.isDebugEnabled()) {
157 _log.debug("Dynamically binding the Liferay data source");
158 }
159
160 DataSource dataSource = InfrastructureUtil.getDataSource();
161
162 if (dataSource == null) {
163 if (_log.isDebugEnabled()) {
164 _log.debug(
165 "Abort dynamically binding the Liferay data source " +
166 "because it is not available");
167 }
168
169 return;
170 }
171
172 Context context = new InitialContext();
173
174 try {
175 try {
176 context.lookup(_JNDI_JDBC);
177 }
178 catch (NamingException ne) {
179 context.createSubcontext(_JNDI_JDBC);
180 }
181
182 try {
183 context.lookup(_JNDI_JDBC_LIFERAY_POOL);
184 }
185 catch (NamingException ne) {
186 context.bind(_JNDI_JDBC_LIFERAY_POOL, dataSource);
187 }
188
189 _dataSourceBindStates.put(servletContextName, true);
190 }
191 catch (Exception e) {
192 if (_log.isWarnEnabled()) {
193 _log.warn(
194 "Unable to dynamically bind the Liferay data source: " +
195 e.getMessage());
196 }
197 }
198 }
199
200 protected void destroyPortlet(Portlet portlet, Set<String> portletIds)
201 throws Exception {
202
203 PortletApp portletApp = portlet.getPortletApp();
204
205 Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
206
207 for (PortletFilter portletFilter : portletFilters) {
208 PortletFilterFactory.destroy(portletFilter);
209 }
210
211 Set<PortletURLListener> portletURLListeners =
212 portletApp.getPortletURLListeners();
213
214 for (PortletURLListener portletURLListener : portletURLListeners) {
215 PortletURLListenerFactory.destroy(portletURLListener);
216 }
217
218 List<Indexer> indexers = portlet.getIndexerInstances();
219
220 for (Indexer indexer : indexers) {
221 IndexerRegistryUtil.unregister(indexer);
222 }
223
224 if (PropsValues.SCHEDULER_ENABLED) {
225 List<SchedulerEntry> schedulerEntries =
226 portlet.getSchedulerEntries();
227
228 if ((schedulerEntries != null) && !schedulerEntries.isEmpty()) {
229 for (SchedulerEntry schedulerEntry : schedulerEntries) {
230 SchedulerEngineHelperUtil.unschedule(
231 schedulerEntry, StorageType.MEMORY_CLUSTERED);
232 }
233 }
234 }
235
236 List<StagedModelDataHandler<?>> stagedModelDataHandlers =
237 portlet.getStagedModelDataHandlerInstances();
238
239 if (stagedModelDataHandlers != null) {
240 StagedModelDataHandlerRegistryUtil.unregister(
241 stagedModelDataHandlers);
242 }
243
244 PollerProcessorUtil.deletePollerProcessor(portlet.getPortletId());
245
246 POPServerUtil.deleteListener(portlet.getPopMessageListenerInstance());
247
248 List<SocialActivityInterpreter> socialActivityInterpreters =
249 portlet.getSocialActivityInterpreterInstances();
250
251 if (socialActivityInterpreters != null) {
252 for (SocialActivityInterpreter socialActivityInterpreter :
253 socialActivityInterpreters) {
254
255 SocialActivityInterpreterLocalServiceUtil.
256 deleteActivityInterpreter(socialActivityInterpreter);
257 }
258 }
259
260 SocialRequestInterpreterLocalServiceUtil.deleteRequestInterpreter(
261 portlet.getSocialRequestInterpreterInstance());
262
263 UserNotificationManagerUtil.deleteUserNotificationDefinitions(
264 portlet.getPortletId());
265
266 List<UserNotificationHandler> userNotificationHandlers =
267 portlet.getUserNotificationHandlerInstances();
268
269 if (userNotificationHandlers != null) {
270 for (UserNotificationHandler userNotificationHandler :
271 userNotificationHandlers) {
272
273 UserNotificationManagerUtil.deleteUserNotificationHandler(
274 userNotificationHandler);
275 }
276 }
277
278 WebDAVUtil.deleteStorage(portlet.getWebDAVStorageInstance());
279
280 XmlRpcServlet.unregisterMethod(portlet.getXmlRpcMethodInstance());
281
282 List<AssetRendererFactory> assetRendererFactories =
283 portlet.getAssetRendererFactoryInstances();
284
285 if (assetRendererFactories != null) {
286 AssetRendererFactoryRegistryUtil.unregister(assetRendererFactories);
287 }
288
289 List<AtomCollectionAdapter<?>> atomCollectionAdapters =
290 portlet.getAtomCollectionAdapterInstances();
291
292 if (atomCollectionAdapters != null) {
293 AtomCollectionAdapterRegistryUtil.unregister(
294 atomCollectionAdapters);
295 }
296
297 List<TrashHandler> trashHandlers = portlet.getTrashHandlerInstances();
298
299 if (trashHandlers != null) {
300 TrashHandlerRegistryUtil.unregister(trashHandlers);
301 }
302
303 List<WorkflowHandler> workflowHandlers =
304 portlet.getWorkflowHandlerInstances();
305
306 if (workflowHandlers != null) {
307 WorkflowHandlerRegistryUtil.unregister(workflowHandlers);
308 }
309
310 PortletInstanceFactoryUtil.destroy(portlet);
311
312 portletIds.add(portlet.getPortletId());
313 }
314
315 protected void doInvokeDeploy(HotDeployEvent hotDeployEvent)
316 throws Exception {
317
318 ServletContext servletContext = hotDeployEvent.getServletContext();
319
320 String servletContextName = servletContext.getServletContextName();
321
322 if (_log.isDebugEnabled()) {
323 _log.debug("Invoking deploy for " + servletContextName);
324 }
325
326 String[] xmls = new String[] {
327 HttpUtil.URLtoString(
328 servletContext.getResource(
329 "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_STANDARD)),
330 HttpUtil.URLtoString(
331 servletContext.getResource(
332 "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_CUSTOM)),
333 HttpUtil.URLtoString(
334 servletContext.getResource("/WEB-INF/liferay-portlet.xml")),
335 HttpUtil.URLtoString(servletContext.getResource("/WEB-INF/web.xml"))
336 };
337
338 if ((xmls[0] == null) && (xmls[1] == null)) {
339 return;
340 }
341
342 if (_log.isInfoEnabled()) {
343 _log.info("Registering portlets for " + servletContextName);
344 }
345
346 List<Portlet> portlets = PortletLocalServiceUtil.initWAR(
347 servletContextName, servletContext, xmls,
348 hotDeployEvent.getPluginPackage());
349
350 boolean portletAppInitialized = false;
351
352 boolean phpPortlet = false;
353 boolean strutsBridges = false;
354
355 PortletBagFactory portletBagFactory = new PortletBagFactory();
356
357 ClassLoader classLoader = hotDeployEvent.getContextClassLoader();
358
359 portletBagFactory.setClassLoader(classLoader);
360
361 portletBagFactory.setServletContext(servletContext);
362 portletBagFactory.setWARFile(true);
363
364 Iterator<Portlet> itr = portlets.iterator();
365
366 while (itr.hasNext()) {
367 Portlet portlet = itr.next();
368
369 PortletBag portletBag = portletBagFactory.create(portlet);
370
371 if (portletBag == null) {
372 itr.remove();
373 }
374 else {
375 if (!portletAppInitialized) {
376 initPortletApp(
377 servletContextName, servletContext, classLoader,
378 portlet);
379
380 portletAppInitialized = true;
381 }
382
383 javax.portlet.Portlet portletInstance =
384 portletBag.getPortletInstance();
385
386 if (ClassUtil.isSubclass(
387 portletInstance.getClass(),
388 PHPPortlet.class.getName())) {
389
390 phpPortlet = true;
391 }
392
393 if (ClassUtil.isSubclass(
394 portletInstance.getClass(),
395 StrutsPortlet.class.getName())) {
396
397 strutsBridges = true;
398 }
399 }
400 }
401
402 if (phpPortlet) {
403 bindDataSource(servletContextName);
404 }
405
406 if (!strutsBridges) {
407 strutsBridges = GetterUtil.getBoolean(
408 servletContext.getInitParameter(
409 "struts-bridges-context-provider"));
410 }
411
412 if (strutsBridges) {
413 servletContext.setAttribute(
414 ServletContextProvider.STRUTS_BRIDGES_CONTEXT_PROVIDER,
415 new LiferayServletContextProvider());
416 }
417
418 String xml = HttpUtil.URLtoString(
419 servletContext.getResource("/WEB-INF/liferay-display.xml"));
420
421 PortletCategory newPortletCategory =
422 PortletLocalServiceUtil.getWARDisplay(servletContextName, xml);
423
424 long[] companyIds = PortalInstances.getCompanyIds();
425
426 for (long companyId : companyIds) {
427 PortletCategory portletCategory = (PortletCategory)WebAppPool.get(
428 companyId, WebKeys.PORTLET_CATEGORY);
429
430 if (portletCategory != null) {
431 portletCategory.merge(newPortletCategory);
432 }
433 else {
434 _log.error(
435 "Unable to register portlet for company " + companyId +
436 " because it does not exist");
437 }
438 }
439
440 processPortletProperties(servletContextName, classLoader);
441
442 for (Portlet portlet : portlets) {
443 List<String> modelNames =
444 ResourceActionsUtil.getPortletModelResources(
445 portlet.getPortletId());
446
447 List<String> portletActions =
448 ResourceActionsUtil.getPortletResourceActions(
449 portlet.getPortletId());
450
451 ResourceActionLocalServiceUtil.checkResourceActions(
452 portlet.getPortletId(), portletActions);
453
454 for (String modelName : modelNames) {
455 List<String> modelActions =
456 ResourceActionsUtil.getModelResourceActions(modelName);
457
458 ResourceActionLocalServiceUtil.checkResourceActions(
459 modelName, modelActions);
460 }
461
462 for (long companyId : companyIds) {
463 Portlet curPortlet = PortletLocalServiceUtil.getPortletById(
464 companyId, portlet.getPortletId());
465
466 PortletLocalServiceUtil.checkPortlet(curPortlet);
467 }
468 }
469
470 for (Portlet portlet : portlets) {
471 boolean ready = GetterUtil.getBoolean(
472 servletContext.getInitParameter(
473 "portlets-ready-by-default"), true);
474
475 portlet.setReady(ready);
476 }
477
478 registerClpMessageListeners(servletContext, classLoader);
479
480 JavadocManagerUtil.load(servletContextName, classLoader);
481
482 DirectServletRegistryUtil.clearServlets();
483
484 _portlets.put(servletContextName, portlets);
485
486 servletContext.setAttribute(WebKeys.PLUGIN_PORTLETS, portlets);
487
488 if (_log.isInfoEnabled()) {
489 if (portlets.size() == 1) {
490 _log.info(
491 "1 portlet for " + servletContextName +
492 " is available for use");
493 }
494 else {
495 _log.info(
496 portlets.size() + " portlets for " + servletContextName +
497 " are available for use");
498 }
499 }
500 }
501
502 protected void doInvokeUndeploy(HotDeployEvent hotDeployEvent)
503 throws Exception {
504
505 ServletContext servletContext = hotDeployEvent.getServletContext();
506
507 String servletContextName = servletContext.getServletContextName();
508
509 if (_log.isDebugEnabled()) {
510 _log.debug("Invoking undeploy for " + servletContextName);
511 }
512
513 List<Portlet> portlets = _portlets.remove(servletContextName);
514
515 if (portlets == null) {
516 return;
517 }
518
519 Set<String> portletIds = new HashSet<String>();
520
521 if (portlets != null) {
522 if (_log.isInfoEnabled()) {
523 _log.info("Unregistering portlets for " + servletContextName);
524 }
525
526 for (Portlet portlet : portlets) {
527 destroyPortlet(portlet, portletIds);
528 }
529 }
530
531 ServletContextPool.remove(servletContextName);
532
533 if (!portletIds.isEmpty()) {
534 long[] companyIds = PortalInstances.getCompanyIds();
535
536 for (long companyId : companyIds) {
537 PortletCategory portletCategory =
538 (PortletCategory)WebAppPool.get(
539 companyId, WebKeys.PORTLET_CATEGORY);
540
541 portletCategory.separate(portletIds);
542 }
543 }
544
545 PortletContextBagPool.remove(servletContextName);
546 PortletResourceBundles.remove(servletContextName);
547
548 unbindDataSource(servletContextName);
549
550 unregisterClpMessageListeners(servletContext);
551
552 JavadocManagerUtil.unload(servletContextName);
553
554 DirectServletRegistryUtil.clearServlets();
555
556 if (_log.isInfoEnabled()) {
557 if (portlets.size() == 1) {
558 _log.info(
559 "1 portlet for " + servletContextName +
560 " was unregistered");
561 }
562 else {
563 _log.info(
564 portlets.size() + " portlets for " + servletContextName +
565 " were unregistered");
566 }
567 }
568 }
569
570 protected void initPortletApp(
571 String servletContextName, ServletContext servletContext,
572 ClassLoader classLoader, Portlet portlet)
573 throws Exception {
574
575 PortletContextBag portletContextBag = new PortletContextBag(
576 servletContextName);
577
578 PortletContextBagPool.put(servletContextName, portletContextBag);
579
580 PortletApp portletApp = portlet.getPortletApp();
581
582 servletContext.setAttribute(PortletServlet.PORTLET_APP, portletApp);
583
584 Map<String, String> customUserAttributes =
585 portletApp.getCustomUserAttributes();
586
587 for (Map.Entry<String, String> entry :
588 customUserAttributes.entrySet()) {
589
590 String attrCustomClass = entry.getValue();
591
592 Class<?> clazz = classLoader.loadClass(attrCustomClass);
593
594 CustomUserAttributes customUserAttributesInstance =
595 (CustomUserAttributes)clazz.newInstance();
596
597 portletContextBag.getCustomUserAttributes().put(
598 attrCustomClass, customUserAttributesInstance);
599 }
600
601 Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
602
603 for (PortletFilter portletFilter : portletFilters) {
604 javax.portlet.filter.PortletFilter portletFilterInstance =
605 (javax.portlet.filter.PortletFilter)newInstance(
606 classLoader,
607 new Class<?>[] {
608 javax.portlet.filter.ActionFilter.class,
609 javax.portlet.filter.EventFilter.class,
610 javax.portlet.filter.PortletFilter.class,
611 javax.portlet.filter.RenderFilter.class,
612 javax.portlet.filter.ResourceFilter.class
613 },
614 portletFilter.getFilterClass());
615
616 portletContextBag.getPortletFilters().put(
617 portletFilter.getFilterName(), portletFilterInstance);
618 }
619
620 InvokerPortlet invokerPortlet = PortletInstanceFactoryUtil.create(
621 portlet, servletContext);
622
623 invokerPortlet.setPortletFilters();
624
625 Set<PortletURLListener> portletURLListeners =
626 portletApp.getPortletURLListeners();
627
628 for (PortletURLListener portletURLListener : portletURLListeners) {
629 PortletURLGenerationListener portletURLListenerInstance =
630 (PortletURLGenerationListener)newInstance(
631 classLoader, PortletURLGenerationListener.class,
632 portletURLListener.getListenerClass());
633
634 portletContextBag.getPortletURLListeners().put(
635 portletURLListener.getListenerClass(),
636 portletURLListenerInstance);
637
638 PortletURLListenerFactory.create(portletURLListener);
639 }
640 }
641
642 protected void processPortletProperties(
643 String servletContextName, ClassLoader classLoader)
644 throws Exception {
645
646 Configuration portletPropertiesConfiguration = null;
647
648 try {
649 portletPropertiesConfiguration =
650 ConfigurationFactoryUtil.getConfiguration(
651 classLoader, "portlet");
652 }
653 catch (Exception e) {
654 if (_log.isDebugEnabled()) {
655 _log.debug("Unable to read portlet.properties");
656 }
657
658 return;
659 }
660
661 Properties portletProperties =
662 portletPropertiesConfiguration.getProperties();
663
664 if (portletProperties.size() == 0) {
665 return;
666 }
667
668 String languageBundleName = portletProperties.getProperty(
669 "language.bundle");
670
671 if (Validator.isNotNull(languageBundleName)) {
672 Locale[] locales = LanguageUtil.getAvailableLocales();
673
674 for (Locale locale : locales) {
675 ResourceBundle resourceBundle = ResourceBundle.getBundle(
676 languageBundleName, locale, classLoader);
677
678 PortletResourceBundles.put(
679 servletContextName, LocaleUtil.toLanguageId(locale),
680 resourceBundle);
681 }
682 }
683
684 String[] resourceActionConfigs = StringUtil.split(
685 portletProperties.getProperty(PropsKeys.RESOURCE_ACTIONS_CONFIGS));
686
687 for (String resourceActionConfig : resourceActionConfigs) {
688 ResourceActionsUtil.read(
689 servletContextName, classLoader, resourceActionConfig);
690 }
691 }
692
693 protected void unbindDataSource(String servletContextName) {
694 Boolean dataSourceBindState = _dataSourceBindStates.remove(
695 servletContextName);
696
697 if (dataSourceBindState == null) {
698 return;
699 }
700
701 try {
702 if (_log.isDebugEnabled()) {
703 _log.debug("Dynamically unbinding the Liferay data source");
704 }
705
706 Context context = new InitialContext();
707
708 try {
709 context.lookup(_JNDI_JDBC_LIFERAY_POOL);
710
711 context.unbind(_JNDI_JDBC_LIFERAY_POOL);
712 }
713 catch (NamingException ne) {
714 }
715
716 try {
717 context.lookup(_JNDI_JDBC);
718
719 context.destroySubcontext(_JNDI_JDBC);
720 }
721 catch (NamingException ne) {
722 }
723 }
724 catch (Exception e) {
725 if (_log.isWarnEnabled()) {
726 _log.warn(
727 "Unable to dynamically unbind the Liferay data source: " +
728 e.getMessage());
729 }
730 }
731 }
732
733 private static final String _JNDI_JDBC = "java_liferay:jdbc";
734
735 private static final String _JNDI_JDBC_LIFERAY_POOL =
736 _JNDI_JDBC + "/LiferayPool";
737
738 private static Log _log = LogFactoryUtil.getLog(
739 PortletHotDeployListener.class);
740
741 private static Map<String, Boolean> _dataSourceBindStates =
742 new HashMap<String, Boolean>();
743 private static Map<String, List<Portlet>> _portlets =
744 new HashMap<String, List<Portlet>>();
745
746 }