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.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.IndexerRegistryUtil;
44  import com.liferay.portal.kernel.search.InvokerIndexer;
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.InvokerPortletDataHandler;
58  import com.liferay.portal.lar.PortletDataHandler;
59  import com.liferay.portal.model.Portlet;
60  import com.liferay.portal.model.PortletApp;
61  import com.liferay.portal.model.PortletCategory;
62  import com.liferay.portal.model.PortletFilter;
63  import com.liferay.portal.model.PortletURLListener;
64  import com.liferay.portal.poller.PollerProcessorUtil;
65  import com.liferay.portal.pop.POPServerUtil;
66  import com.liferay.portal.security.permission.ResourceActionsUtil;
67  import com.liferay.portal.service.PortletLocalServiceUtil;
68  import com.liferay.portal.service.ResourceActionLocalServiceUtil;
69  import com.liferay.portal.service.ResourceCodeLocalServiceUtil;
70  import com.liferay.portal.util.Portal;
71  import com.liferay.portal.util.PortalInstances;
72  import com.liferay.portal.util.PortalUtil;
73  import com.liferay.portal.util.PropsValues;
74  import com.liferay.portal.util.WebAppPool;
75  import com.liferay.portal.util.WebKeys;
76  import com.liferay.portal.velocity.VelocityContextPool;
77  import com.liferay.portal.webdav.WebDAVStorage;
78  import com.liferay.portal.webdav.WebDAVUtil;
79  import com.liferay.portlet.ControlPanelEntry;
80  import com.liferay.portlet.CustomUserAttributes;
81  import com.liferay.portlet.PortletBagImpl;
82  import com.liferay.portlet.PortletConfigFactory;
83  import com.liferay.portlet.PortletContextBag;
84  import com.liferay.portlet.PortletContextBagPool;
85  import com.liferay.portlet.PortletFilterFactory;
86  import com.liferay.portlet.PortletInstanceFactoryUtil;
87  import com.liferay.portlet.PortletPreferencesSerializer;
88  import com.liferay.portlet.PortletResourceBundles;
89  import com.liferay.portlet.PortletURLListenerFactory;
90  import com.liferay.portlet.social.model.SocialActivityInterpreter;
91  import com.liferay.portlet.social.model.SocialRequestInterpreter;
92  import com.liferay.portlet.social.model.impl.SocialActivityInterpreterImpl;
93  import com.liferay.portlet.social.model.impl.SocialRequestInterpreterImpl;
94  import com.liferay.portlet.social.service.SocialActivityInterpreterLocalServiceUtil;
95  import com.liferay.portlet.social.service.SocialRequestInterpreterLocalServiceUtil;
96  
97  import java.util.HashMap;
98  import java.util.HashSet;
99  import java.util.Iterator;
100 import java.util.List;
101 import java.util.Locale;
102 import java.util.Map;
103 import java.util.MissingResourceException;
104 import java.util.Properties;
105 import java.util.ResourceBundle;
106 import java.util.Set;
107 
108 import javax.portlet.PortletConfig;
109 import javax.portlet.PortletContext;
110 import javax.portlet.PortletURLGenerationListener;
111 import javax.portlet.PreferencesValidator;
112 
113 import javax.servlet.ServletContext;
114 
115 import org.apache.portals.bridges.struts.StrutsPortlet;
116 
117 /**
118  * <a href="PortletHotDeployListener.java.html"><b><i>View Source</i></b></a>
119  *
120  * @author Brian Wing Shun Chan
121  * @author Brian Myunghun Kim
122  * @author Ivica Cardic
123  * @author Raymond Augé
124  *
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 = new InvokerIndexer(
482                 indexerInstance, portletClassLoader);
483 
484             for (String className : indexerInstance.getClassNames()) {
485                 IndexerRegistryUtil.register(className, indexerInstance);
486             }
487         }
488 
489         OpenSearch openSearchInstance = null;
490 
491         if (Validator.isNotNull(portlet.getOpenSearchClass())) {
492             openSearchInstance = (OpenSearch)portletClassLoader.loadClass(
493                 portlet.getOpenSearchClass()).newInstance();
494         }
495 
496         Scheduler schedulerInstance = null;
497 
498         if (PropsValues.SCHEDULER_ENABLED &&
499             Validator.isNotNull(portlet.getSchedulerClass())) {
500 
501             schedulerInstance = (Scheduler)portletClassLoader.loadClass(
502                 portlet.getSchedulerClass()).newInstance();
503 
504             schedulerInstance.schedule();
505         }
506 
507         FriendlyURLMapper friendlyURLMapperInstance = null;
508 
509         if (Validator.isNotNull(portlet.getFriendlyURLMapperClass())) {
510             friendlyURLMapperInstance =
511                 (FriendlyURLMapper)portletClassLoader.loadClass(
512                     portlet.getFriendlyURLMapperClass()).newInstance();
513         }
514 
515         URLEncoder urlEncoderInstance = null;
516 
517         if (Validator.isNotNull(portlet.getURLEncoderClass())) {
518             urlEncoderInstance = (URLEncoder)portletClassLoader.loadClass(
519                 portlet.getURLEncoderClass()).newInstance();
520         }
521 
522         PortletDataHandler portletDataHandlerInstance = null;
523 
524         if (Validator.isNotNull(portlet.getPortletDataHandlerClass())) {
525             portletDataHandlerInstance =
526                 (PortletDataHandler)portletClassLoader.loadClass(
527                     portlet.getPortletDataHandlerClass()).newInstance();
528 
529             portletDataHandlerInstance = new InvokerPortletDataHandler(
530                 portletDataHandlerInstance, portletClassLoader);
531         }
532 
533         PortletLayoutListener portletLayoutListenerInstance = null;
534 
535         if (Validator.isNotNull(portlet.getPortletLayoutListenerClass())) {
536             portletLayoutListenerInstance =
537                 (PortletLayoutListener)portletClassLoader.loadClass(
538                     portlet.getPortletLayoutListenerClass()).newInstance();
539         }
540 
541         PollerProcessor pollerProcessorInstance = null;
542 
543         if (Validator.isNotNull(portlet.getPollerProcessorClass())) {
544             pollerProcessorInstance =
545                 (PollerProcessor)portletClassLoader.loadClass(
546                     portlet.getPollerProcessorClass()).newInstance();
547 
548             pollerProcessorInstance = new InvokerPollerProcessor(
549                 pollerProcessorInstance, portletClassLoader);
550 
551             PollerProcessorUtil.addPollerProcessor(
552                 portlet.getPortletId(), pollerProcessorInstance);
553         }
554 
555         MessageListener popMessageListenerInstance = null;
556 
557         if (Validator.isNotNull(portlet.getPopMessageListenerClass())) {
558             popMessageListenerInstance =
559                 (MessageListener)portletClassLoader.loadClass(
560                     portlet.getPopMessageListenerClass()).newInstance();
561 
562             POPServerUtil.addListener(popMessageListenerInstance);
563         }
564 
565         SocialActivityInterpreter socialActivityInterpreterInstance = null;
566 
567         if (Validator.isNotNull(portlet.getSocialActivityInterpreterClass())) {
568             socialActivityInterpreterInstance =
569                 (SocialActivityInterpreter)portletClassLoader.loadClass(
570                     portlet.getSocialActivityInterpreterClass()).newInstance();
571 
572             socialActivityInterpreterInstance =
573                 new SocialActivityInterpreterImpl(
574                     portlet.getPortletId(), socialActivityInterpreterInstance);
575 
576             SocialActivityInterpreterLocalServiceUtil.addActivityInterpreter(
577                 socialActivityInterpreterInstance);
578         }
579 
580         SocialRequestInterpreter socialRequestInterpreterInstance = null;
581 
582         if (Validator.isNotNull(portlet.getSocialRequestInterpreterClass())) {
583             socialRequestInterpreterInstance =
584                 (SocialRequestInterpreter)portletClassLoader.loadClass(
585                     portlet.getSocialRequestInterpreterClass()).newInstance();
586 
587             socialRequestInterpreterInstance = new SocialRequestInterpreterImpl(
588                 portlet.getPortletId(), socialRequestInterpreterInstance);
589 
590             SocialRequestInterpreterLocalServiceUtil.addRequestInterpreter(
591                 socialRequestInterpreterInstance);
592         }
593 
594         WebDAVStorage webDAVStorageInstance = null;
595 
596         if (Validator.isNotNull(portlet.getWebDAVStorageClass())) {
597             webDAVStorageInstance = (WebDAVStorage)portletClassLoader.loadClass(
598                 portlet.getWebDAVStorageClass()).newInstance();
599 
600             webDAVStorageInstance.setToken(portlet.getWebDAVStorageToken());
601 
602             WebDAVUtil.addStorage(webDAVStorageInstance);
603         }
604 
605         ControlPanelEntry controlPanelEntryInstance = null;
606 
607         if (Validator.isNotNull(portlet.getControlPanelEntryClass())) {
608             controlPanelEntryInstance =
609                 (ControlPanelEntry)portletClassLoader.loadClass(
610                     portlet.getControlPanelEntryClass()).newInstance();
611         }
612 
613         PreferencesValidator preferencesValidatorInstance = null;
614 
615         if (Validator.isNotNull(portlet.getPreferencesValidator())) {
616             preferencesValidatorInstance =
617                 (PreferencesValidator)portletClassLoader.loadClass(
618                     portlet.getPreferencesValidator()).newInstance();
619 
620             try {
621                 if (PropsValues.PREFERENCE_VALIDATE_ON_STARTUP) {
622                     preferencesValidatorInstance.validate(
623                         PortletPreferencesSerializer.fromDefaultXML(
624                             portlet.getDefaultPreferences()));
625                 }
626             }
627             catch (Exception e) {
628                 _log.warn(
629                     "Portlet with the name " + portlet.getPortletId() +
630                         " does not have valid default preferences");
631             }
632         }
633 
634         Map<String, ResourceBundle> resourceBundles = null;
635 
636         if (Validator.isNotNull(portlet.getResourceBundle())) {
637             resourceBundles = new HashMap<String, ResourceBundle>();
638 
639             initResourceBundle(
640                 resourceBundles, portlet, portletClassLoader,
641                 LocaleUtil.getDefault());
642 
643             Iterator<String> supportLocalesItr =
644                 portlet.getSupportedLocales().iterator();
645 
646             while (supportLocalesItr.hasNext()) {
647                 String supportedLocale = supportLocalesItr.next();
648 
649                 Locale locale = LocaleUtil.fromLanguageId(supportedLocale);
650 
651                 initResourceBundle(
652                     resourceBundles, portlet, portletClassLoader, locale);
653             }
654         }
655 
656         PortletBag portletBag = new PortletBagImpl(
657             portlet.getPortletId(), servletContext, portletInstance,
658             configurationActionInstance, indexerInstance, openSearchInstance,
659             schedulerInstance, friendlyURLMapperInstance, urlEncoderInstance,
660             portletDataHandlerInstance, portletLayoutListenerInstance,
661             pollerProcessorInstance, popMessageListenerInstance,
662             socialActivityInterpreterInstance, socialRequestInterpreterInstance,
663             webDAVStorageInstance, controlPanelEntryInstance,
664             preferencesValidatorInstance, resourceBundles);
665 
666         PortletBagPool.put(portlet.getPortletId(), portletBag);
667 
668         if (!_portletAppInitialized) {
669             initPortletApp(
670                 portlet, servletContextName, servletContext,
671                 portletClassLoader);
672 
673             _portletAppInitialized = true;
674         }
675 
676         try {
677             PortletInstanceFactoryUtil.create(portlet, servletContext);
678         }
679         catch (Exception e) {
680             _log.error(e, e);
681         }
682     }
683 
684     protected void initPortletApp(
685             Portlet portlet, String servletContextName,
686             ServletContext servletContext, ClassLoader portletClassLoader)
687         throws Exception {
688 
689         PortletConfig portletConfig = PortletConfigFactory.create(
690             portlet, servletContext);
691 
692         PortletContext portletContext = portletConfig.getPortletContext();
693 
694         PortletContextBag portletContextBag = new PortletContextBag(
695             servletContextName);
696 
697         PortletContextBagPool.put(servletContextName, portletContextBag);
698 
699         PortletApp portletApp = portlet.getPortletApp();
700 
701         Map<String, String> customUserAttributes =
702             portletApp.getCustomUserAttributes();
703 
704         for (Map.Entry<String, String> entry :
705                 customUserAttributes.entrySet()) {
706 
707             String attrCustomClass = entry.getValue();
708 
709             CustomUserAttributes customUserAttributesInstance =
710                 (CustomUserAttributes)portletClassLoader.loadClass(
711                     attrCustomClass).newInstance();
712 
713             portletContextBag.getCustomUserAttributes().put(
714                 attrCustomClass, customUserAttributesInstance);
715         }
716 
717         Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
718 
719         for (PortletFilter portletFilter : portletFilters) {
720             javax.portlet.filter.PortletFilter portletFilterInstance =
721                 (javax.portlet.filter.PortletFilter)
722                     portletClassLoader.loadClass(
723                         portletFilter.getFilterClass()).newInstance();
724 
725             portletContextBag.getPortletFilters().put(
726                 portletFilter.getFilterName(), portletFilterInstance);
727 
728             PortletFilterFactory.create(portletFilter, portletContext);
729         }
730 
731         Set<PortletURLListener> portletURLListeners =
732             portletApp.getPortletURLListeners();
733 
734         for (PortletURLListener portletURLListener : portletURLListeners) {
735             PortletURLGenerationListener portletURLListenerInstance =
736                 (PortletURLGenerationListener)portletClassLoader.loadClass(
737                     portletURLListener.getListenerClass()).newInstance();
738 
739             portletContextBag.getPortletURLListeners().put(
740                 portletURLListener.getListenerClass(),
741                 portletURLListenerInstance);
742 
743             PortletURLListenerFactory.create(portletURLListener);
744         }
745     }
746 
747     protected void initResourceBundle(
748         Map<String, ResourceBundle> resourceBundles, Portlet portlet,
749         ClassLoader portletClassLoader, Locale locale) {
750 
751         try {
752             ResourceBundle resourceBundle = ResourceBundle.getBundle(
753                 portlet.getResourceBundle(), locale, portletClassLoader);
754 
755             resourceBundles.put(
756                 LocaleUtil.toLanguageId(locale), resourceBundle);
757         }
758         catch (MissingResourceException mre) {
759             _log.warn(mre.getMessage());
760         }
761     }
762 
763     protected void processPortletProperties(
764             String servletContextName, ClassLoader portletClassLoader)
765         throws Exception {
766 
767         Configuration portletPropertiesConfiguration = null;
768 
769         try {
770             portletPropertiesConfiguration =
771                 ConfigurationFactoryUtil.getConfiguration(
772                     portletClassLoader, "portlet");
773         }
774         catch (Exception e) {
775             if (_log.isDebugEnabled()) {
776                 _log.debug("Unable to read portlet.properties");
777             }
778 
779             return;
780         }
781 
782         Properties portletProperties =
783             portletPropertiesConfiguration.getProperties();
784 
785         if (portletProperties.size() == 0) {
786             return;
787         }
788 
789         String languageBundleName = portletProperties.getProperty(
790             "language.bundle");
791 
792         if (Validator.isNotNull(languageBundleName)) {
793             Locale[] locales = LanguageUtil.getAvailableLocales();
794 
795             for (int i = 0; i < locales.length; i++) {
796                 ResourceBundle bundle = ResourceBundle.getBundle(
797                     languageBundleName, locales[i], portletClassLoader);
798 
799                 PortletResourceBundles.put(
800                     servletContextName, LocaleUtil.toLanguageId(locales[i]),
801                     bundle);
802             }
803         }
804 
805         String[] resourceActionConfigs = StringUtil.split(
806             portletProperties.getProperty("resource.actions.configs"));
807 
808         for (int i = 0; i < resourceActionConfigs.length; i++) {
809             ResourceActionsUtil.read(
810                 servletContextName, portletClassLoader,
811                 resourceActionConfigs[i]);
812         }
813     }
814 
815     private static Log _log =
816         LogFactoryUtil.getLog(PortletHotDeployListener.class);
817 
818     private static Map<String, ObjectValuePair<long[], List<Portlet>>> _vars =
819         new HashMap<String, ObjectValuePair<long[], List<Portlet>>>();
820 
821     private boolean _portletAppInitialized;
822     private boolean _strutsBridges;
823 
824 }