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