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