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