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