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