1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.deploy.hot;
16  
17  import com.liferay.portal.apache.bridges.struts.LiferayServletContextProvider;
18  import com.liferay.portal.kernel.configuration.Configuration;
19  import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
20  import com.liferay.portal.kernel.deploy.hot.BaseHotDeployListener;
21  import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
22  import com.liferay.portal.kernel.deploy.hot.HotDeployException;
23  import com.liferay.portal.kernel.language.LanguageUtil;
24  import com.liferay.portal.kernel.log.Log;
25  import com.liferay.portal.kernel.log.LogFactoryUtil;
26  import com.liferay.portal.kernel.poller.PollerProcessor;
27  import com.liferay.portal.kernel.portlet.ConfigurationAction;
28  import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
29  import com.liferay.portal.kernel.portlet.PortletBag;
30  import com.liferay.portal.kernel.portlet.PortletBagPool;
31  import com.liferay.portal.kernel.portlet.PortletLayoutListener;
32  import com.liferay.portal.kernel.scheduler.SchedulerEngineUtil;
33  import com.liferay.portal.kernel.scheduler.SchedulerEntry;
34  import com.liferay.portal.kernel.search.Indexer;
35  import com.liferay.portal.kernel.search.IndexerRegistryUtil;
36  import com.liferay.portal.kernel.search.OpenSearch;
37  import com.liferay.portal.kernel.servlet.PortletServlet;
38  import com.liferay.portal.kernel.servlet.ServletContextProvider;
39  import com.liferay.portal.kernel.servlet.URLEncoder;
40  import com.liferay.portal.kernel.util.ClassUtil;
41  import com.liferay.portal.kernel.util.GetterUtil;
42  import com.liferay.portal.kernel.util.HttpUtil;
43  import com.liferay.portal.kernel.util.LocaleUtil;
44  import com.liferay.portal.kernel.util.ObjectValuePair;
45  import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
46  import com.liferay.portal.kernel.util.StringUtil;
47  import com.liferay.portal.kernel.util.Validator;
48  import com.liferay.portal.kernel.workflow.WorkflowHandler;
49  import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
50  import com.liferay.portal.kernel.xmlrpc.Method;
51  import com.liferay.portal.lar.PortletDataHandler;
52  import com.liferay.portal.model.Portlet;
53  import com.liferay.portal.model.PortletApp;
54  import com.liferay.portal.model.PortletCategory;
55  import com.liferay.portal.model.PortletFilter;
56  import com.liferay.portal.model.PortletURLListener;
57  import com.liferay.portal.poller.PollerProcessorUtil;
58  import com.liferay.portal.pop.POPServerUtil;
59  import com.liferay.portal.security.permission.ResourceActionsUtil;
60  import com.liferay.portal.service.PortletLocalServiceUtil;
61  import com.liferay.portal.service.ResourceActionLocalServiceUtil;
62  import com.liferay.portal.service.ResourceCodeLocalServiceUtil;
63  import com.liferay.portal.util.Portal;
64  import com.liferay.portal.util.PortalInstances;
65  import com.liferay.portal.util.PortalUtil;
66  import com.liferay.portal.util.PropsValues;
67  import com.liferay.portal.util.WebAppPool;
68  import com.liferay.portal.util.WebKeys;
69  import com.liferay.portal.velocity.VelocityContextPool;
70  import com.liferay.portal.webdav.WebDAVStorage;
71  import com.liferay.portal.webdav.WebDAVUtil;
72  import com.liferay.portal.xmlrpc.XmlRpcServlet;
73  import com.liferay.portlet.ControlPanelEntry;
74  import com.liferay.portlet.CustomUserAttributes;
75  import com.liferay.portlet.PortletBagImpl;
76  import com.liferay.portlet.PortletConfigFactory;
77  import com.liferay.portlet.PortletContextBag;
78  import com.liferay.portlet.PortletContextBagPool;
79  import com.liferay.portlet.PortletFilterFactory;
80  import com.liferay.portlet.PortletInstanceFactoryUtil;
81  import com.liferay.portlet.PortletPreferencesSerializer;
82  import com.liferay.portlet.PortletResourceBundles;
83  import com.liferay.portlet.PortletURLListenerFactory;
84  import com.liferay.portlet.asset.AssetRendererFactoryRegistryUtil;
85  import com.liferay.portlet.asset.model.AssetRendererFactory;
86  import com.liferay.portlet.expando.model.CustomAttributesDisplay;
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.ArrayList;
95  import java.util.HashMap;
96  import java.util.HashSet;
97  import java.util.Iterator;
98  import java.util.List;
99  import java.util.Locale;
100 import java.util.Map;
101 import java.util.MissingResourceException;
102 import java.util.Properties;
103 import java.util.ResourceBundle;
104 import java.util.Set;
105 
106 import javax.portlet.PortletConfig;
107 import javax.portlet.PortletContext;
108 import javax.portlet.PortletURLGenerationListener;
109 import javax.portlet.PreferencesValidator;
110 
111 import javax.servlet.ServletContext;
112 
113 import org.apache.portals.bridges.struts.StrutsPortlet;
114 
115 /**
116  * <a href="PortletHotDeployListener.java.html"><b><i>View Source</i></b></a>
117  *
118  * @author Brian Wing Shun Chan
119  * @author Brian Myunghun Kim
120  * @author Ivica Cardic
121  * @author Raymond Augé
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             IndexerRegistryUtil.unregister(indexer);
167         }
168 
169         if (PropsValues.SCHEDULER_ENABLED){
170             List<SchedulerEntry> schedulerEntries =
171                 portlet.getSchedulerEntries();
172 
173             if ((schedulerEntries != null) && !schedulerEntries.isEmpty()) {
174                 for (SchedulerEntry schedulerEntry : schedulerEntries) {
175                     SchedulerEngineUtil.unschedule(schedulerEntry);
176                 }
177             }
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         XmlRpcServlet.unregisterMethod(portlet.getXmlRpcMethodInstance());
193 
194         List<AssetRendererFactory> assetRendererFactories =
195             portlet.getAssetRendererFactoryInstances();
196 
197         if (assetRendererFactories != null) {
198             AssetRendererFactoryRegistryUtil.unregister(assetRendererFactories);
199         }
200 
201         List<WorkflowHandler> workflowHandlers =
202             portlet.getWorkflowHandlerInstances();
203 
204         if (workflowHandlers != null) {
205             WorkflowHandlerRegistryUtil.unregister(workflowHandlers);
206         }
207 
208         PortletInstanceFactoryUtil.destroy(portlet);
209 
210         portletIds.add(portlet.getPortletId());
211     }
212 
213     protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
214 
215         // Servlet context
216 
217         ServletContext servletContext = event.getServletContext();
218 
219         String servletContextName = servletContext.getServletContextName();
220 
221         if (_log.isDebugEnabled()) {
222             _log.debug("Invoking deploy for " + servletContextName);
223         }
224 
225         // Company ids
226 
227         long[] companyIds = PortalInstances.getCompanyIds();
228 
229         // Initialize portlets
230 
231         String[] xmls = new String[] {
232             HttpUtil.URLtoString(servletContext.getResource(
233                 "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_STANDARD)),
234             HttpUtil.URLtoString(servletContext.getResource(
235                 "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_CUSTOM)),
236             HttpUtil.URLtoString(servletContext.getResource(
237                 "/WEB-INF/liferay-portlet.xml")),
238             HttpUtil.URLtoString(servletContext.getResource("/WEB-INF/web.xml"))
239         };
240 
241         if (xmls[0] == null) {
242             return;
243         }
244 
245         if (_log.isInfoEnabled()) {
246             _log.info("Registering portlets for " + servletContextName);
247         }
248 
249         List<Portlet> portlets = PortletLocalServiceUtil.initWAR(
250             servletContextName, servletContext, xmls, event.getPluginPackage());
251 
252         // Class loader
253 
254         ClassLoader portletClassLoader = event.getContextClassLoader();
255 
256         servletContext.setAttribute(
257             PortletServlet.PORTLET_CLASS_LOADER, portletClassLoader);
258 
259         // Portlet context wrapper
260 
261         _portletAppInitialized = false;
262         _strutsBridges = false;
263 
264         Iterator<Portlet> itr = portlets.iterator();
265 
266         while (itr.hasNext()) {
267             Portlet portlet = itr.next();
268 
269             initPortlet(portlet, servletContext, portletClassLoader, itr);
270         }
271 
272         // Struts bridges
273 
274         if (!_strutsBridges) {
275             _strutsBridges = GetterUtil.getBoolean(
276                 servletContext.getInitParameter(
277                     "struts-bridges-context-provider"));
278         }
279 
280         if (_strutsBridges) {
281             servletContext.setAttribute(
282                 ServletContextProvider.STRUTS_BRIDGES_CONTEXT_PROVIDER,
283                 new LiferayServletContextProvider());
284         }
285 
286         // Portlet display
287 
288         String xml = HttpUtil.URLtoString(servletContext.getResource(
289             "/WEB-INF/liferay-display.xml"));
290 
291         PortletCategory newPortletCategory =
292             PortletLocalServiceUtil.getWARDisplay(servletContextName, xml);
293 
294         for (int i = 0; i < companyIds.length; i++) {
295             long companyId = companyIds[i];
296 
297             PortletCategory portletCategory =
298                 (PortletCategory)WebAppPool.get(
299                     String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
300 
301             if (portletCategory != null) {
302                 portletCategory.merge(newPortletCategory);
303             }
304             else {
305                 _log.error(
306                     "Unable to register portlet for company " + companyId +
307                         " because it does not exist");
308             }
309         }
310 
311         // Portlet properties
312 
313         processPortletProperties(servletContextName, portletClassLoader);
314 
315         // Resource actions, resource codes, and check
316 
317         itr = portlets.iterator();
318 
319         while (itr.hasNext()) {
320             Portlet portlet = itr.next();
321 
322             List<String> modelNames =
323                 ResourceActionsUtil.getPortletModelResources(
324                     portlet.getPortletId());
325 
326             for (long companyId : companyIds) {
327                 ResourceCodeLocalServiceUtil.checkResourceCodes(
328                     companyId, portlet.getPortletId());
329 
330                 for (String modelName : modelNames) {
331                     ResourceCodeLocalServiceUtil.checkResourceCodes(
332                         companyId, modelName);
333                 }
334             }
335 
336             List<String> portletActions =
337                 ResourceActionsUtil.getPortletResourceActions(
338                     portlet.getPortletId());
339 
340             ResourceActionLocalServiceUtil.checkResourceActions(
341                 portlet.getPortletId(), portletActions);
342 
343             for (String modelName : modelNames) {
344                 List<String> modelActions =
345                     ResourceActionsUtil.getModelResourceActions(modelName);
346 
347                 ResourceActionLocalServiceUtil.checkResourceActions(
348                     modelName, modelActions);
349             }
350 
351             for (long companyId : companyIds) {
352                 Portlet curPortlet = PortletLocalServiceUtil.getPortletById(
353                     companyId, portlet.getPortletId());
354 
355                 PortletLocalServiceUtil.checkPortlet(curPortlet);
356             }
357         }
358 
359         // ClpMessageListener
360 
361         registerClpMessageListeners(servletContext, portletClassLoader);
362 
363         // Variables
364 
365         _vars.put(
366             servletContextName,
367             new ObjectValuePair<long[], List<Portlet>>(
368                 companyIds, portlets));
369 
370         if (_log.isInfoEnabled()) {
371             if (portlets.size() == 1) {
372                 _log.info(
373                     "1 portlet for " + servletContextName +
374                         " is available for use");
375             }
376             else {
377                 _log.info(
378                     portlets.size() + " portlets for " + servletContextName +
379                         " are available for use");
380             }
381         }
382     }
383 
384     protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
385         ServletContext servletContext = event.getServletContext();
386 
387         String servletContextName = servletContext.getServletContextName();
388 
389         if (_log.isDebugEnabled()) {
390             _log.debug("Invoking undeploy for " + servletContextName);
391         }
392 
393         ObjectValuePair<long[], List<Portlet>> ovp =
394             _vars.remove(servletContextName);
395 
396         if (ovp == null) {
397             return;
398         }
399 
400         long[] companyIds = ovp.getKey();
401         List<Portlet> portlets = ovp.getValue();
402 
403         Set<String> portletIds = new HashSet<String>();
404 
405         if (portlets != null) {
406             if (_log.isInfoEnabled()) {
407                 _log.info(
408                     "Unregistering portlets for " + servletContextName);
409             }
410 
411             Iterator<Portlet> itr = portlets.iterator();
412 
413             while (itr.hasNext()) {
414                 Portlet portlet = itr.next();
415 
416                 destroyPortlet(portlet, portletIds);
417             }
418         }
419 
420         if (portletIds.size() > 0) {
421             for (int i = 0; i < companyIds.length; i++) {
422                 long companyId = companyIds[i];
423 
424                 PortletCategory portletCategory =
425                     (PortletCategory)WebAppPool.get(
426                         String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
427 
428                 portletCategory.separate(portletIds);
429             }
430         }
431 
432         PortletResourceBundles.remove(servletContextName);
433 
434         unregisterClpMessageListeners(servletContext);
435 
436         if (_log.isInfoEnabled()) {
437             if (portlets.size() == 1) {
438                 _log.info(
439                     "1 portlet for " + servletContextName +
440                         " was unregistered");
441             }
442             else {
443                 _log.info(
444                     portlets.size() + " portlets for " + servletContextName +
445                         " was unregistered");
446             }
447         }
448     }
449 
450     protected void initPortlet(
451             Portlet portlet, ServletContext servletContext,
452             ClassLoader portletClassLoader, Iterator<Portlet> portletsItr)
453         throws Exception {
454 
455         String servletContextName = servletContext.getServletContextName();
456 
457         PortletApp portletApp = portlet.getPortletApp();
458 
459         if (!portletApp.isWARFile()) {
460             String contextPath = PortalUtil.getPathContext();
461 
462             servletContext = VelocityContextPool.get(contextPath);
463 
464             portletClassLoader = PortalClassLoaderUtil.getClassLoader();
465         }
466 
467         Class<?> portletClass = null;
468 
469         try {
470             portletClass = portletClassLoader.loadClass(
471                 portlet.getPortletClass());
472         }
473         catch (Throwable e) {
474             _log.error(e, e);
475 
476             portletsItr.remove();
477 
478             PortletLocalServiceUtil.destroyPortlet(portlet);
479 
480             return;
481         }
482 
483         javax.portlet.Portlet portletInstance =
484             (javax.portlet.Portlet)portletClass.newInstance();
485 
486         if (ClassUtil.isSubclass(portletClass, StrutsPortlet.class.getName())) {
487             _strutsBridges = true;
488         }
489 
490         ConfigurationAction configurationActionInstance = null;
491 
492         if (Validator.isNotNull(portlet.getConfigurationActionClass())) {
493             configurationActionInstance = (ConfigurationAction)newInstance(
494                 portletClassLoader, ConfigurationAction.class,
495                 portlet.getConfigurationActionClass());
496         }
497 
498         Indexer indexerInstance = null;
499 
500         if (Validator.isNotNull(portlet.getIndexerClass())) {
501             indexerInstance = (Indexer)newInstance(
502                 portletClassLoader, Indexer.class, portlet.getIndexerClass());
503 
504             IndexerRegistryUtil.register(indexerInstance);
505         }
506 
507         OpenSearch openSearchInstance = null;
508 
509         if (Validator.isNotNull(portlet.getOpenSearchClass())) {
510             openSearchInstance = (OpenSearch)newInstance(
511                 portletClassLoader, OpenSearch.class,
512                 portlet.getOpenSearchClass());
513         }
514 
515         if (PropsValues.SCHEDULER_ENABLED){
516             List<SchedulerEntry> schedulerEntries =
517                 portlet.getSchedulerEntries();
518 
519             if ((schedulerEntries != null) && !schedulerEntries.isEmpty()) {
520                 for (SchedulerEntry schedulerEntry : schedulerEntries) {
521                     SchedulerEngineUtil.schedule(
522                         schedulerEntry, portletClassLoader);
523                 }
524             }
525         }
526 
527         FriendlyURLMapper friendlyURLMapperInstance = null;
528 
529         if (Validator.isNotNull(portlet.getFriendlyURLMapperClass())) {
530             friendlyURLMapperInstance = (FriendlyURLMapper)newInstance(
531                 portletClassLoader, FriendlyURLMapper.class,
532                 portlet.getFriendlyURLMapperClass());
533         }
534 
535         URLEncoder urlEncoderInstance = null;
536 
537         if (Validator.isNotNull(portlet.getURLEncoderClass())) {
538             urlEncoderInstance = (URLEncoder)newInstance(
539                 portletClassLoader, URLEncoder.class,
540                 portlet.getURLEncoderClass());
541         }
542 
543         PortletDataHandler portletDataHandlerInstance = null;
544 
545         if (Validator.isNotNull(portlet.getPortletDataHandlerClass())) {
546             portletDataHandlerInstance = (PortletDataHandler)newInstance(
547                 portletClassLoader, PortletDataHandler.class,
548                 portlet.getPortletDataHandlerClass());
549         }
550 
551         PortletLayoutListener portletLayoutListenerInstance = null;
552 
553         if (Validator.isNotNull(portlet.getPortletLayoutListenerClass())) {
554             portletLayoutListenerInstance = (PortletLayoutListener)newInstance(
555                 portletClassLoader, PortletLayoutListener.class,
556                 portlet.getPortletLayoutListenerClass());
557         }
558 
559         PollerProcessor pollerProcessorInstance = null;
560 
561         if (Validator.isNotNull(portlet.getPollerProcessorClass())) {
562             pollerProcessorInstance = (PollerProcessor)newInstance(
563                 portletClassLoader, PollerProcessor.class,
564                 portlet.getPollerProcessorClass());
565 
566             PollerProcessorUtil.addPollerProcessor(
567                 portlet.getPortletId(), pollerProcessorInstance);
568         }
569 
570         com.liferay.portal.kernel.pop.MessageListener
571             popMessageListenerInstance = null;
572 
573         if (Validator.isNotNull(portlet.getPopMessageListenerClass())) {
574             popMessageListenerInstance =
575                 (com.liferay.portal.kernel.pop.MessageListener)newInstance(
576                     portletClassLoader,
577                     com.liferay.portal.kernel.pop.MessageListener.class,
578                     portlet.getPopMessageListenerClass());
579 
580             POPServerUtil.addListener(popMessageListenerInstance);
581         }
582 
583         SocialActivityInterpreter socialActivityInterpreterInstance = null;
584 
585         if (Validator.isNotNull(portlet.getSocialActivityInterpreterClass())) {
586             socialActivityInterpreterInstance =
587                 (SocialActivityInterpreter)newInstance(
588                     portletClassLoader, SocialActivityInterpreter.class,
589                     portlet.getSocialActivityInterpreterClass());
590 
591             socialActivityInterpreterInstance =
592                 new SocialActivityInterpreterImpl(
593                     portlet.getPortletId(), socialActivityInterpreterInstance);
594 
595             SocialActivityInterpreterLocalServiceUtil.addActivityInterpreter(
596                 socialActivityInterpreterInstance);
597         }
598 
599         SocialRequestInterpreter socialRequestInterpreterInstance = null;
600 
601         if (Validator.isNotNull(portlet.getSocialRequestInterpreterClass())) {
602             socialRequestInterpreterInstance =
603                 (SocialRequestInterpreter)newInstance(
604                     portletClassLoader, SocialRequestInterpreter.class,
605                     portlet.getSocialRequestInterpreterClass());
606 
607             socialRequestInterpreterInstance = new SocialRequestInterpreterImpl(
608                 portlet.getPortletId(), socialRequestInterpreterInstance);
609 
610             SocialRequestInterpreterLocalServiceUtil.addRequestInterpreter(
611                 socialRequestInterpreterInstance);
612         }
613 
614         WebDAVStorage webDAVStorageInstance = null;
615 
616         if (Validator.isNotNull(portlet.getWebDAVStorageClass())) {
617             webDAVStorageInstance = (WebDAVStorage)newInstance(
618                 portletClassLoader, WebDAVStorage.class,
619                 portlet.getWebDAVStorageClass());
620 
621             webDAVStorageInstance.setToken(portlet.getWebDAVStorageToken());
622 
623             WebDAVUtil.addStorage(webDAVStorageInstance);
624         }
625 
626         Method xmlRpcMethodInstance = null;
627 
628         if (Validator.isNotNull(portlet.getXmlRpcMethodClass())) {
629             xmlRpcMethodInstance = (Method)newInstance(
630                 portletClassLoader, Method.class,
631                 portlet.getXmlRpcMethodClass());
632 
633             XmlRpcServlet.registerMethod(xmlRpcMethodInstance);
634         }
635 
636         ControlPanelEntry controlPanelEntryInstance = null;
637 
638         if (Validator.isNotNull(portlet.getControlPanelEntryClass())) {
639             controlPanelEntryInstance = (ControlPanelEntry)newInstance(
640                 portletClassLoader, ControlPanelEntry.class,
641                 portlet.getControlPanelEntryClass());
642         }
643 
644         List<AssetRendererFactory> assetRendererFactoryInstances =
645             new ArrayList<AssetRendererFactory>();
646 
647         for (String assetRendererFactoryClass :
648                 portlet.getAssetRendererFactoryClasses()) {
649 
650             AssetRendererFactory assetRendererFactoryInstance =
651                 (AssetRendererFactory)newInstance(
652                     portletClassLoader, AssetRendererFactory.class,
653                     assetRendererFactoryClass);
654 
655             assetRendererFactoryInstance.setClassNameId(
656                 PortalUtil.getClassNameId(
657                     assetRendererFactoryInstance.getClassName()));
658             assetRendererFactoryInstance.setPortletId(portlet.getPortletId());
659 
660             assetRendererFactoryInstances.add(assetRendererFactoryInstance);
661 
662             AssetRendererFactoryRegistryUtil.register(
663                 assetRendererFactoryInstance);
664         }
665 
666         List<CustomAttributesDisplay> customAttributesDisplayInstances =
667             new ArrayList<CustomAttributesDisplay>();
668 
669         for (String customAttributesDisplayClass :
670                 portlet.getCustomAttributesDisplayClasses()) {
671 
672             CustomAttributesDisplay customAttributesDisplayInstance =
673                 (CustomAttributesDisplay)newInstance(
674                     portletClassLoader, CustomAttributesDisplay.class,
675                     customAttributesDisplayClass);
676 
677             customAttributesDisplayInstance.setClassNameId(
678                 PortalUtil.getClassNameId(
679                     customAttributesDisplayInstance.getClassName()));
680             customAttributesDisplayInstance.setPortletId(
681                 portlet.getPortletId());
682 
683             customAttributesDisplayInstances.add(
684                 customAttributesDisplayInstance);
685         }
686 
687         List<WorkflowHandler> workflowHandlerInstances =
688             new ArrayList<WorkflowHandler>();
689 
690         for (String workflowHandlerClass :
691                 portlet.getWorkflowHandlerClasses()) {
692 
693             WorkflowHandler workflowHandlerInstance =
694                 (WorkflowHandler)newInstance(
695                     portletClassLoader, WorkflowHandler.class,
696                     workflowHandlerClass);
697 
698             workflowHandlerInstances.add(workflowHandlerInstance);
699 
700             WorkflowHandlerRegistryUtil.register(workflowHandlerInstance);
701         }
702 
703         PreferencesValidator preferencesValidatorInstance = null;
704 
705         if (Validator.isNotNull(portlet.getPreferencesValidator())) {
706             preferencesValidatorInstance = (PreferencesValidator)newInstance(
707                 portletClassLoader, PreferencesValidator.class,
708                 portlet.getPreferencesValidator());
709 
710             try {
711                 if (PropsValues.PREFERENCE_VALIDATE_ON_STARTUP) {
712                     preferencesValidatorInstance.validate(
713                         PortletPreferencesSerializer.fromDefaultXML(
714                             portlet.getDefaultPreferences()));
715                 }
716             }
717             catch (Exception e) {
718                 _log.warn(
719                     "Portlet with the name " + portlet.getPortletId() +
720                         " does not have valid default preferences");
721             }
722         }
723 
724         Map<String, ResourceBundle> resourceBundles = null;
725 
726         if (Validator.isNotNull(portlet.getResourceBundle())) {
727             resourceBundles = new HashMap<String, ResourceBundle>();
728 
729             initResourceBundle(
730                 resourceBundles, portlet, portletClassLoader,
731                 LocaleUtil.getDefault());
732 
733             Iterator<String> supportLocalesItr =
734                 portlet.getSupportedLocales().iterator();
735 
736             while (supportLocalesItr.hasNext()) {
737                 String supportedLocale = supportLocalesItr.next();
738 
739                 Locale locale = LocaleUtil.fromLanguageId(supportedLocale);
740 
741                 initResourceBundle(
742                     resourceBundles, portlet, portletClassLoader, locale);
743             }
744         }
745 
746         PortletBag portletBag = new PortletBagImpl(
747             portlet.getPortletId(), servletContext, portletInstance,
748             configurationActionInstance, indexerInstance, openSearchInstance,
749             friendlyURLMapperInstance, urlEncoderInstance,
750             portletDataHandlerInstance, portletLayoutListenerInstance,
751             pollerProcessorInstance, popMessageListenerInstance,
752             socialActivityInterpreterInstance, socialRequestInterpreterInstance,
753             webDAVStorageInstance, xmlRpcMethodInstance,
754             controlPanelEntryInstance, assetRendererFactoryInstances,
755             customAttributesDisplayInstances, workflowHandlerInstances,
756             preferencesValidatorInstance, resourceBundles);
757 
758         PortletBagPool.put(portlet.getPortletId(), portletBag);
759 
760         if (!_portletAppInitialized) {
761             initPortletApp(
762                 portlet, servletContextName, servletContext,
763                 portletClassLoader);
764 
765             _portletAppInitialized = true;
766         }
767 
768         try {
769             PortletInstanceFactoryUtil.create(portlet, servletContext);
770         }
771         catch (Exception e) {
772             _log.error(e, e);
773         }
774     }
775 
776     protected void initPortletApp(
777             Portlet portlet, String servletContextName,
778             ServletContext servletContext, ClassLoader portletClassLoader)
779         throws Exception {
780 
781         PortletConfig portletConfig = PortletConfigFactory.create(
782             portlet, servletContext);
783 
784         PortletContext portletContext = portletConfig.getPortletContext();
785 
786         PortletContextBag portletContextBag = new PortletContextBag(
787             servletContextName);
788 
789         PortletContextBagPool.put(servletContextName, portletContextBag);
790 
791         PortletApp portletApp = portlet.getPortletApp();
792 
793         Map<String, String> customUserAttributes =
794             portletApp.getCustomUserAttributes();
795 
796         for (Map.Entry<String, String> entry :
797                 customUserAttributes.entrySet()) {
798 
799             String attrCustomClass = entry.getValue();
800 
801             CustomUserAttributes customUserAttributesInstance =
802                 (CustomUserAttributes)portletClassLoader.loadClass(
803                     attrCustomClass).newInstance();
804 
805             portletContextBag.getCustomUserAttributes().put(
806                 attrCustomClass, customUserAttributesInstance);
807         }
808 
809         Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
810 
811         for (PortletFilter portletFilter : portletFilters) {
812             javax.portlet.filter.PortletFilter portletFilterInstance =
813                 (javax.portlet.filter.PortletFilter)newInstance(
814                     portletClassLoader,
815                     new Class<?>[] {
816                         javax.portlet.filter.ActionFilter.class,
817                         javax.portlet.filter.EventFilter.class,
818                         javax.portlet.filter.PortletFilter.class,
819                         javax.portlet.filter.RenderFilter.class,
820                         javax.portlet.filter.ResourceFilter.class
821                     },
822                     portletFilter.getFilterClass());
823 
824             portletContextBag.getPortletFilters().put(
825                 portletFilter.getFilterName(), portletFilterInstance);
826 
827             PortletFilterFactory.create(portletFilter, portletContext);
828         }
829 
830         Set<PortletURLListener> portletURLListeners =
831             portletApp.getPortletURLListeners();
832 
833         for (PortletURLListener portletURLListener : portletURLListeners) {
834             PortletURLGenerationListener portletURLListenerInstance =
835                 (PortletURLGenerationListener)newInstance(
836                     portletClassLoader, PortletURLGenerationListener.class,
837                     portletURLListener.getListenerClass());
838 
839             portletContextBag.getPortletURLListeners().put(
840                 portletURLListener.getListenerClass(),
841                 portletURLListenerInstance);
842 
843             PortletURLListenerFactory.create(portletURLListener);
844         }
845     }
846 
847     protected void initResourceBundle(
848         Map<String, ResourceBundle> resourceBundles, Portlet portlet,
849         ClassLoader portletClassLoader, Locale locale) {
850 
851         try {
852             ResourceBundle resourceBundle = ResourceBundle.getBundle(
853                 portlet.getResourceBundle(), locale, portletClassLoader);
854 
855             resourceBundles.put(
856                 LocaleUtil.toLanguageId(locale), resourceBundle);
857         }
858         catch (MissingResourceException mre) {
859             _log.warn(mre.getMessage());
860         }
861     }
862 
863     protected void processPortletProperties(
864             String servletContextName, ClassLoader portletClassLoader)
865         throws Exception {
866 
867         Configuration portletPropertiesConfiguration = null;
868 
869         try {
870             portletPropertiesConfiguration =
871                 ConfigurationFactoryUtil.getConfiguration(
872                     portletClassLoader, "portlet");
873         }
874         catch (Exception e) {
875             if (_log.isDebugEnabled()) {
876                 _log.debug("Unable to read portlet.properties");
877             }
878 
879             return;
880         }
881 
882         Properties portletProperties =
883             portletPropertiesConfiguration.getProperties();
884 
885         if (portletProperties.size() == 0) {
886             return;
887         }
888 
889         String languageBundleName = portletProperties.getProperty(
890             "language.bundle");
891 
892         if (Validator.isNotNull(languageBundleName)) {
893             Locale[] locales = LanguageUtil.getAvailableLocales();
894 
895             for (int i = 0; i < locales.length; i++) {
896                 ResourceBundle bundle = ResourceBundle.getBundle(
897                     languageBundleName, locales[i], portletClassLoader);
898 
899                 PortletResourceBundles.put(
900                     servletContextName, LocaleUtil.toLanguageId(locales[i]),
901                     bundle);
902             }
903         }
904 
905         String[] resourceActionConfigs = StringUtil.split(
906             portletProperties.getProperty("resource.actions.configs"));
907 
908         for (int i = 0; i < resourceActionConfigs.length; i++) {
909             ResourceActionsUtil.read(
910                 servletContextName, portletClassLoader,
911                 resourceActionConfigs[i]);
912         }
913     }
914 
915     private static Log _log = LogFactoryUtil.getLog(
916         PortletHotDeployListener.class);
917 
918     private static Map<String, ObjectValuePair<long[], List<Portlet>>> _vars =
919         new HashMap<String, ObjectValuePair<long[], List<Portlet>>>();
920 
921     private boolean _portletAppInitialized;
922     private boolean _strutsBridges;
923 
924 }