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