1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions 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.cache.CacheRegistry;
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.lar.PortletDataHandler;
34  import com.liferay.portal.kernel.pop.MessageListener;
35  import com.liferay.portal.kernel.portlet.ConfigurationAction;
36  import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
37  import com.liferay.portal.kernel.portlet.PortletLayoutListener;
38  import com.liferay.portal.kernel.search.Indexer;
39  import com.liferay.portal.kernel.servlet.PortletServlet;
40  import com.liferay.portal.kernel.servlet.ServletContextProvider;
41  import com.liferay.portal.kernel.servlet.URLEncoder;
42  import com.liferay.portal.kernel.util.ClassUtil;
43  import com.liferay.portal.kernel.util.GetterUtil;
44  import com.liferay.portal.kernel.util.HttpUtil;
45  import com.liferay.portal.kernel.util.LocaleUtil;
46  import com.liferay.portal.kernel.util.ObjectValuePair;
47  import com.liferay.portal.kernel.util.StringUtil;
48  import com.liferay.portal.kernel.util.Validator;
49  import com.liferay.portal.model.Portlet;
50  import com.liferay.portal.model.PortletApp;
51  import com.liferay.portal.model.PortletCategory;
52  import com.liferay.portal.model.PortletFilter;
53  import com.liferay.portal.model.PortletURLListener;
54  import com.liferay.portal.pop.POPServerUtil;
55  import com.liferay.portal.security.permission.ResourceActionsUtil;
56  import com.liferay.portal.service.PortletLocalServiceUtil;
57  import com.liferay.portal.service.ServiceComponentLocalServiceUtil;
58  import com.liferay.portal.util.Portal;
59  import com.liferay.portal.util.PortalInstances;
60  import com.liferay.portal.util.PropsValues;
61  import com.liferay.portal.util.WebAppPool;
62  import com.liferay.portal.util.WebKeys;
63  import com.liferay.portlet.CustomUserAttributes;
64  import com.liferay.portlet.PortletBag;
65  import com.liferay.portlet.PortletBagPool;
66  import com.liferay.portlet.PortletConfigFactory;
67  import com.liferay.portlet.PortletContextBag;
68  import com.liferay.portlet.PortletContextBagPool;
69  import com.liferay.portlet.PortletFilterFactory;
70  import com.liferay.portlet.PortletInstanceFactory;
71  import com.liferay.portlet.PortletPreferencesSerializer;
72  import com.liferay.portlet.PortletResourceBundles;
73  import com.liferay.portlet.PortletURLListenerFactory;
74  import com.liferay.portlet.social.model.SocialActivityInterpreter;
75  import com.liferay.portlet.social.model.SocialRequestInterpreter;
76  import com.liferay.portlet.social.model.impl.SocialActivityInterpreterImpl;
77  import com.liferay.portlet.social.model.impl.SocialRequestInterpreterImpl;
78  import com.liferay.portlet.social.service.SocialActivityInterpreterLocalServiceUtil;
79  import com.liferay.portlet.social.service.SocialRequestInterpreterLocalServiceUtil;
80  
81  import java.util.HashMap;
82  import java.util.HashSet;
83  import java.util.Iterator;
84  import java.util.List;
85  import java.util.Locale;
86  import java.util.Map;
87  import java.util.MissingResourceException;
88  import java.util.Properties;
89  import java.util.ResourceBundle;
90  import java.util.Set;
91  
92  import javax.portlet.PortletConfig;
93  import javax.portlet.PortletContext;
94  import javax.portlet.PortletURLGenerationListener;
95  import javax.portlet.PreferencesValidator;
96  
97  import javax.servlet.ServletContext;
98  
99  import org.apache.commons.logging.Log;
100 import org.apache.commons.logging.LogFactory;
101 import org.apache.portals.bridges.struts.StrutsPortlet;
102 
103 /**
104  * <a href="PortletHotDeployListener.java.html"><b><i>View Source</i></b></a>
105  *
106  * @author Brian Wing Shun Chan
107  * @author Brian Myunghun Kim
108  * @author Ivica Cardic
109  *
110  */
111 public class PortletHotDeployListener extends BaseHotDeployListener {
112 
113     public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
114         try {
115             doInvokeDeploy(event);
116         }
117         catch (Exception e) {
118             throwHotDeployException(
119                 event, "Error registering portlets for ", e);
120         }
121     }
122 
123     public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
124         try {
125             doInvokeUndeploy(event);
126         }
127         catch (Exception e) {
128             throwHotDeployException(
129                 event, "Error unregistering portlets for ", e);
130         }
131     }
132 
133     protected void destroyPortlet(Portlet portlet, Set<String> portletIds)
134         throws Exception {
135 
136         PortletApp portletApp = portlet.getPortletApp();
137 
138         Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
139 
140         for (PortletFilter portletFilter : portletFilters) {
141             PortletFilterFactory.destroy(portletFilter);
142         }
143 
144         Set<PortletURLListener> portletURLListeners =
145             portletApp.getPortletURLListeners();
146 
147         for (PortletURLListener portletURLListener : portletURLListeners) {
148             PortletURLListenerFactory.destroy(portletURLListener);
149         }
150 
151         Scheduler scheduler = portlet.getSchedulerInstance();
152 
153         if (scheduler != null) {
154             scheduler.unschedule();
155         }
156 
157         POPServerUtil.deleteListener(portlet.getPopMessageListenerInstance());
158 
159         SocialActivityInterpreterLocalServiceUtil.deleteActivityInterpreter(
160             portlet.getSocialActivityInterpreterInstance());
161 
162         SocialRequestInterpreterLocalServiceUtil.deleteRequestInterpreter(
163             portlet.getSocialRequestInterpreterInstance());
164 
165         PortletInstanceFactory.destroy(portlet);
166 
167         portletIds.add(portlet.getPortletId());
168     }
169 
170     protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
171 
172         // Servlet context
173 
174         ServletContext servletContext = event.getServletContext();
175 
176         String servletContextName = servletContext.getServletContextName();
177 
178         if (_log.isDebugEnabled()) {
179             _log.debug("Invoking deploy for " + servletContextName);
180         }
181 
182         // Company ids
183 
184         long[] companyIds = PortalInstances.getCompanyIds();
185 
186         // Initialize portlets
187 
188         String[] xmls = new String[] {
189             HttpUtil.URLtoString(servletContext.getResource(
190                 "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_STANDARD)),
191             HttpUtil.URLtoString(servletContext.getResource(
192                 "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_CUSTOM)),
193             HttpUtil.URLtoString(servletContext.getResource(
194                 "/WEB-INF/liferay-portlet.xml")),
195             HttpUtil.URLtoString(servletContext.getResource("/WEB-INF/web.xml"))
196         };
197 
198         if (xmls[0] == null) {
199             return;
200         }
201 
202         if (_log.isInfoEnabled()) {
203             _log.info("Registering portlets for " + servletContextName);
204         }
205 
206         List<Portlet> portlets = PortletLocalServiceUtil.initWAR(
207             servletContextName, xmls, event.getPluginPackage());
208 
209         if (_log.isInfoEnabled()) {
210             _log.info(
211                 portlets.size() + " portlets for " + servletContextName +
212                     " are ready for registration");
213         }
214 
215         // Class loader
216 
217         ClassLoader portletClassLoader = event.getContextClassLoader();
218 
219         servletContext.setAttribute(
220             PortletServlet.PORTLET_CLASS_LOADER, portletClassLoader);
221 
222         // Portlet context wrapper
223 
224         _strutsBridges = false;
225 
226         Iterator<Portlet> portletsItr = portlets.iterator();
227 
228         while (portletsItr.hasNext()) {
229             Portlet portlet = portletsItr.next();
230 
231             initPortlet(
232                 portlet, servletContext, portletClassLoader, portletsItr);
233         }
234 
235         // Struts bridges
236 
237         if (!_strutsBridges) {
238             _strutsBridges = GetterUtil.getBoolean(
239                 servletContext.getInitParameter(
240                     "struts-bridges-context-provider"));
241         }
242 
243         if (_strutsBridges) {
244             servletContext.setAttribute(
245                 ServletContextProvider.STRUTS_BRIDGES_CONTEXT_PROVIDER,
246                 new LiferayServletContextProvider());
247         }
248 
249         // Portlet display
250 
251         String xml = HttpUtil.URLtoString(servletContext.getResource(
252             "/WEB-INF/liferay-display.xml"));
253 
254         PortletCategory newPortletCategory =
255             PortletLocalServiceUtil.getWARDisplay(servletContextName, xml);
256 
257         for (int i = 0; i < companyIds.length; i++) {
258             long companyId = companyIds[i];
259 
260             PortletCategory portletCategory =
261                 (PortletCategory)WebAppPool.get(
262                     String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
263 
264             if (portletCategory != null) {
265                 portletCategory.merge(newPortletCategory);
266             }
267             else {
268                 _log.error(
269                     "Unable to register portlet for company " + companyId +
270                         " because it does not exist");
271             }
272         }
273 
274         // Portlet properties
275 
276         processPortletProperties(servletContextName, portletClassLoader);
277 
278         // Service builder properties
279 
280         _processServiceBuilderProperties = false;
281 
282         processServiceBuilderProperties(servletContext, portletClassLoader);
283 
284         // Variables
285 
286         _vars.put(
287             servletContextName,
288             new ObjectValuePair<long[], List<Portlet>>(
289                 companyIds, portlets));
290 
291         if (_log.isInfoEnabled()) {
292             _log.info(
293                 portlets.size() + " portlets for " + servletContextName +
294                     " registered successfully");
295         }
296     }
297 
298     protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
299         ServletContext servletContext = event.getServletContext();
300 
301         String servletContextName = servletContext.getServletContextName();
302 
303         if (_log.isDebugEnabled()) {
304             _log.debug("Invoking undeploy for " + servletContextName);
305         }
306 
307         ObjectValuePair<long[], List<Portlet>> ovp =
308             _vars.remove(servletContextName);
309 
310         if (ovp == null) {
311             return;
312         }
313 
314         long[] companyIds = ovp.getKey();
315         List<Portlet> portlets = ovp.getValue();
316 
317         Set<String> portletIds = new HashSet<String>();
318 
319         if (portlets != null) {
320             if (_log.isInfoEnabled()) {
321                 _log.info(
322                     "Unregistering portlets for " + servletContextName);
323             }
324 
325             Iterator<Portlet> itr = portlets.iterator();
326 
327             while (itr.hasNext()) {
328                 Portlet portlet = itr.next();
329 
330                 destroyPortlet(portlet, portletIds);
331             }
332         }
333 
334         if (portletIds.size() > 0) {
335             for (int i = 0; i < companyIds.length; i++) {
336                 long companyId = companyIds[i];
337 
338                 PortletCategory portletCategory =
339                     (PortletCategory)WebAppPool.get(
340                         String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
341 
342                 portletCategory.separate(portletIds);
343             }
344         }
345 
346         PortletResourceBundles.remove(servletContextName);
347 
348         if (_processServiceBuilderProperties) {
349             CacheRegistry.clear();
350         }
351 
352         if (_log.isInfoEnabled()) {
353             _log.info(
354                 portlets.size() + " portlets for " + servletContextName +
355                     " unregistered successfully");
356         }
357     }
358 
359     protected void initPortlet(
360             Portlet portlet, ServletContext servletContext,
361             ClassLoader portletClassLoader, Iterator<Portlet> portletsItr)
362         throws Exception {
363 
364         Class<?> portletClass = null;
365 
366         try {
367             portletClass = portletClassLoader.loadClass(
368                 portlet.getPortletClass());
369         }
370         catch (Exception e) {
371             _log.error(e, e);
372 
373             portletsItr.remove();
374 
375             PortletLocalServiceUtil.destroyPortlet(portlet);
376 
377             return;
378         }
379 
380         javax.portlet.Portlet portletInstance =
381             (javax.portlet.Portlet)portletClass.newInstance();
382 
383         if (ClassUtil.isSubclass(portletClass, StrutsPortlet.class.getName())) {
384             _strutsBridges = true;
385         }
386 
387         ConfigurationAction configurationActionInstance = null;
388 
389         if (Validator.isNotNull(portlet.getConfigurationActionClass())) {
390             configurationActionInstance =
391                 (ConfigurationAction)portletClassLoader.loadClass(
392                     portlet.getConfigurationActionClass()).newInstance();
393         }
394 
395         Indexer indexerInstance = null;
396 
397         if (Validator.isNotNull(portlet.getIndexerClass())) {
398             indexerInstance = (Indexer)portletClassLoader.loadClass(
399                 portlet.getIndexerClass()).newInstance();
400         }
401 
402         Scheduler schedulerInstance = null;
403 
404         if (PropsValues.SCHEDULER_ENABLED &&
405             Validator.isNotNull(portlet.getSchedulerClass())) {
406 
407             schedulerInstance = (Scheduler)portletClassLoader.loadClass(
408                 portlet.getSchedulerClass()).newInstance();
409 
410             schedulerInstance.schedule();
411         }
412 
413         FriendlyURLMapper friendlyURLMapperInstance = null;
414 
415         if (Validator.isNotNull(portlet.getFriendlyURLMapperClass())) {
416             friendlyURLMapperInstance =
417                 (FriendlyURLMapper)portletClassLoader.loadClass(
418                     portlet.getFriendlyURLMapperClass()).newInstance();
419         }
420 
421         URLEncoder urlEncoderInstance = null;
422 
423         if (Validator.isNotNull(portlet.getURLEncoderClass())) {
424             urlEncoderInstance = (URLEncoder)portletClassLoader.loadClass(
425                 portlet.getURLEncoderClass()).newInstance();
426         }
427 
428         PortletDataHandler portletDataHandlerInstance = null;
429 
430         if (Validator.isNotNull(portlet.getPortletDataHandlerClass())) {
431             portletDataHandlerInstance =
432                 (PortletDataHandler)portletClassLoader.loadClass(
433                     portlet.getPortletDataHandlerClass()).newInstance();
434         }
435 
436         PortletLayoutListener portletLayoutListenerInstance = null;
437 
438         if (Validator.isNotNull(portlet.getPortletLayoutListenerClass())) {
439             portletLayoutListenerInstance =
440                 (PortletLayoutListener)portletClassLoader.loadClass(
441                     portlet.getPortletLayoutListenerClass()).newInstance();
442         }
443 
444         MessageListener popMessageListenerInstance = null;
445 
446         if (Validator.isNotNull(portlet.getPopMessageListenerClass())) {
447             popMessageListenerInstance =
448                 (MessageListener)portletClassLoader.loadClass(
449                     portlet.getPopMessageListenerClass()).newInstance();
450 
451             POPServerUtil.addListener(popMessageListenerInstance);
452         }
453 
454         SocialActivityInterpreter socialActivityInterpreterInstance = null;
455 
456         if (Validator.isNotNull(portlet.getSocialActivityInterpreterClass())) {
457             socialActivityInterpreterInstance =
458                 (SocialActivityInterpreter)portletClassLoader.loadClass(
459                     portlet.getSocialActivityInterpreterClass()).newInstance();
460 
461             socialActivityInterpreterInstance =
462                 new SocialActivityInterpreterImpl(
463                     portlet.getPortletId(), socialActivityInterpreterInstance);
464 
465             SocialActivityInterpreterLocalServiceUtil.addActivityInterpreter(
466                 socialActivityInterpreterInstance);
467         }
468 
469         SocialRequestInterpreter socialRequestInterpreterInstance = null;
470 
471         if (Validator.isNotNull(portlet.getSocialRequestInterpreterClass())) {
472             socialRequestInterpreterInstance =
473                 (SocialRequestInterpreter)portletClassLoader.loadClass(
474                     portlet.getSocialRequestInterpreterClass()).newInstance();
475 
476             socialRequestInterpreterInstance = new SocialRequestInterpreterImpl(
477                 portlet.getPortletId(), socialRequestInterpreterInstance);
478 
479             SocialRequestInterpreterLocalServiceUtil.addRequestInterpreter(
480                 socialRequestInterpreterInstance);
481         }
482 
483         PreferencesValidator prefsValidatorInstance = null;
484 
485         if (Validator.isNotNull(portlet.getPreferencesValidator())) {
486             prefsValidatorInstance =
487                 (PreferencesValidator)portletClassLoader.loadClass(
488                     portlet.getPreferencesValidator()).newInstance();
489 
490             try {
491                 if (PropsValues.PREFERENCE_VALIDATE_ON_STARTUP) {
492                     prefsValidatorInstance.validate(
493                         PortletPreferencesSerializer.fromDefaultXML(
494                             portlet.getDefaultPreferences()));
495                 }
496             }
497             catch (Exception e) {
498                 _log.warn(
499                     "Portlet with the name " + portlet.getPortletId() +
500                         " does not have valid default preferences");
501             }
502         }
503 
504         Map<String, ResourceBundle> resourceBundles = null;
505 
506         if (Validator.isNotNull(portlet.getResourceBundle())) {
507             resourceBundles = new HashMap<String, ResourceBundle>();
508 
509             initResourceBundle(
510                 resourceBundles, portlet, portletClassLoader,
511                 LocaleUtil.getDefault());
512 
513             Iterator<String> supportLocalesItr =
514                 portlet.getSupportedLocales().iterator();
515 
516             while (supportLocalesItr.hasNext()) {
517                 String supportedLocale = supportLocalesItr.next();
518 
519                 Locale locale = LocaleUtil.fromLanguageId(supportedLocale);
520 
521                 initResourceBundle(
522                     resourceBundles, portlet, portletClassLoader, locale);
523             }
524         }
525 
526         PortletBag portletBag = new PortletBag(
527             portlet.getPortletId(), servletContext, portletInstance,
528             configurationActionInstance, indexerInstance, schedulerInstance,
529             friendlyURLMapperInstance, urlEncoderInstance,
530             portletDataHandlerInstance, portletLayoutListenerInstance,
531             popMessageListenerInstance, socialActivityInterpreterInstance,
532             socialRequestInterpreterInstance, prefsValidatorInstance,
533             resourceBundles);
534 
535         PortletBagPool.put(portlet.getPortletId(), portletBag);
536 
537         if (!portletsItr.hasNext()) {
538             initPortletApp(portlet, servletContext, portletClassLoader);
539         }
540 
541         try {
542             PortletInstanceFactory.create(portlet, servletContext);
543         }
544         catch (Exception e) {
545             _log.error(e, e);
546         }
547     }
548 
549     protected void initPortletApp(
550             Portlet portlet, ServletContext servletContext,
551             ClassLoader portletClassLoader)
552         throws Exception {
553 
554         String servletContextName = servletContext.getServletContextName();
555 
556         PortletConfig portletConfig = PortletConfigFactory.create(
557             portlet, servletContext);
558 
559         PortletContext portletContext = portletConfig.getPortletContext();
560 
561         PortletContextBag portletContextBag = new PortletContextBag(
562             servletContextName);
563 
564         PortletContextBagPool.put(servletContextName, portletContextBag);
565 
566         PortletApp portletApp = portlet.getPortletApp();
567 
568         Map<String, String> customUserAttributes =
569             portletApp.getCustomUserAttributes();
570 
571         for (Map.Entry<String, String> entry :
572                 customUserAttributes.entrySet()) {
573 
574             String attrCustomClass = entry.getValue();
575 
576             CustomUserAttributes customUserAttributesInstance =
577                 (CustomUserAttributes)portletClassLoader.loadClass(
578                     attrCustomClass).newInstance();
579 
580             portletContextBag.getCustomUserAttributes().put(
581                 attrCustomClass, customUserAttributesInstance);
582         }
583 
584         Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
585 
586         for (PortletFilter portletFilter : portletFilters) {
587             javax.portlet.filter.PortletFilter portletFilterInstance =
588                 (javax.portlet.filter.PortletFilter)
589                     portletClassLoader.loadClass(
590                         portletFilter.getFilterClass()).newInstance();
591 
592             portletContextBag.getPortletFilters().put(
593                 portletFilter.getFilterName(), portletFilterInstance);
594 
595             PortletFilterFactory.create(portletFilter, portletContext);
596         }
597 
598         Set<PortletURLListener> portletURLListeners =
599             portletApp.getPortletURLListeners();
600 
601         for (PortletURLListener portletURLListener : portletURLListeners) {
602             PortletURLGenerationListener portletURLListenerInstance =
603                 (PortletURLGenerationListener)portletClassLoader.loadClass(
604                     portletURLListener.getListenerClass()).newInstance();
605 
606             portletContextBag.getPortletURLListeners().put(
607                 portletURLListener.getListenerClass(),
608                 portletURLListenerInstance);
609 
610             PortletURLListenerFactory.create(portletURLListener);
611         }
612     }
613 
614     protected void initResourceBundle(
615         Map<String, ResourceBundle> resourceBundles, Portlet portlet,
616         ClassLoader portletClassLoader, Locale locale) {
617 
618         try {
619             ResourceBundle resourceBundle = ResourceBundle.getBundle(
620                 portlet.getResourceBundle(), locale, portletClassLoader);
621 
622             resourceBundles.put(
623                 LocaleUtil.toLanguageId(locale), resourceBundle);
624         }
625         catch (MissingResourceException mre) {
626             _log.warn(mre.getMessage());
627         }
628     }
629 
630     protected void processPortletProperties(
631             String servletContextName, ClassLoader portletClassLoader)
632         throws Exception {
633 
634         Configuration portletPropertiesConfiguration = null;
635 
636         try {
637             portletPropertiesConfiguration =
638                 ConfigurationFactoryUtil.getConfiguration(
639                     portletClassLoader, "portlet");
640         }
641         catch (Exception e) {
642             if (_log.isDebugEnabled()) {
643                 _log.debug("Unable to read portlet.properties");
644             }
645         }
646 
647         if (portletPropertiesConfiguration == null) {
648             return;
649         }
650 
651         Properties portletProperties =
652             portletPropertiesConfiguration.getProperties();
653 
654         if (portletProperties.size() == 0) {
655             return;
656         }
657 
658         String languageBundleName = portletProperties.getProperty(
659             "language.bundle");
660 
661         if (Validator.isNotNull(languageBundleName)) {
662             Locale[] locales = LanguageUtil.getAvailableLocales();
663 
664             for (int i = 0; i < locales.length; i++) {
665                 ResourceBundle bundle = ResourceBundle.getBundle(
666                     languageBundleName, locales[i], portletClassLoader);
667 
668                 PortletResourceBundles.put(
669                     servletContextName, LocaleUtil.toLanguageId(locales[i]),
670                     bundle);
671             }
672         }
673 
674         String[] resourceActionConfigs = StringUtil.split(
675             portletProperties.getProperty("resource.actions.configs"));
676 
677         for (int i = 0; i < resourceActionConfigs.length; i++) {
678             ResourceActionsUtil.read(
679                 servletContextName, portletClassLoader,
680                 resourceActionConfigs[i]);
681         }
682     }
683 
684     protected void processServiceBuilderProperties(
685             ServletContext servletContext, ClassLoader portletClassLoader)
686         throws Exception {
687 
688         Configuration serviceBuilderPropertiesConfiguration = null;
689 
690         try {
691             serviceBuilderPropertiesConfiguration =
692                 ConfigurationFactoryUtil.getConfiguration(
693                     portletClassLoader, "service");
694         }
695         catch (Exception e) {
696             if (_log.isDebugEnabled()) {
697                 _log.debug("Unable to read service.properties");
698             }
699         }
700 
701         if (serviceBuilderPropertiesConfiguration == null) {
702             return;
703         }
704 
705         Properties serviceBuilderProperties =
706             serviceBuilderPropertiesConfiguration.getProperties();
707 
708         if (serviceBuilderProperties.size() == 0) {
709             return;
710         }
711 
712         String buildNamespace = GetterUtil.getString(
713             serviceBuilderProperties.getProperty("build.namespace"));
714         long buildNumber = GetterUtil.getLong(
715             serviceBuilderProperties.getProperty("build.number"));
716         long buildDate = GetterUtil.getLong(
717             serviceBuilderProperties.getProperty("build.date"));
718 
719         if (_log.isDebugEnabled()) {
720             _log.debug("Build namespace " + buildNamespace);
721             _log.debug("Build number " + buildNumber);
722             _log.debug("Build date " + buildDate);
723         }
724 
725         ServiceComponentLocalServiceUtil.updateServiceComponent(
726             servletContext, portletClassLoader, buildNamespace, buildNumber,
727             buildDate);
728 
729         _processServiceBuilderProperties = true;
730     }
731 
732     private static Log _log = LogFactory.getLog(PortletHotDeployListener.class);
733 
734     private static Map<String, ObjectValuePair<long[], List<Portlet>>> _vars =
735         new HashMap<String, ObjectValuePair<long[], List<Portlet>>>();
736 
737     private boolean _strutsBridges;
738     private boolean _processServiceBuilderProperties;
739 
740 }