1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
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 /**
104  * <a href="PortletHotDeployListener.java.html"><b><i>View Source</i></b></a>
105  *
106  * @author Brian Wing Shun Chan
107  * @author Brian Myunghun Kim
108  * @author Ivica Cardic
109  *
110  */
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         // Servlet context
173 
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         // Company ids
183 
184         long[] companyIds = PortalInstances.getCompanyIds();
185 
186         // Initialize portlets
187 
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         // Class loader
216 
217         ClassLoader portletClassLoader = event.getContextClassLoader();
218 
219         servletContext.setAttribute(
220             PortletServlet.PORTLET_CLASS_LOADER, portletClassLoader);
221 
222         // Portlet context wrapper
223 
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         // Struts bridges
237 
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         // Portlet display
251 
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         // Portlet properties
276 
277         processPortletProperties(servletContextName, portletClassLoader);
278 
279         // Variables
280 
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 }