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