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