001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.deploy.hot;
016    
017    import com.liferay.portal.apache.bridges.struts.LiferayServletContextProvider;
018    import com.liferay.portal.kernel.atom.AtomCollectionAdapter;
019    import com.liferay.portal.kernel.atom.AtomCollectionAdapterRegistryUtil;
020    import com.liferay.portal.kernel.concurrent.LockRegistry;
021    import com.liferay.portal.kernel.configuration.Configuration;
022    import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
023    import com.liferay.portal.kernel.deploy.hot.BaseHotDeployListener;
024    import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
025    import com.liferay.portal.kernel.deploy.hot.HotDeployException;
026    import com.liferay.portal.kernel.javadoc.JavadocManagerUtil;
027    import com.liferay.portal.kernel.language.LanguageUtil;
028    import com.liferay.portal.kernel.log.Log;
029    import com.liferay.portal.kernel.log.LogFactoryUtil;
030    import com.liferay.portal.kernel.portlet.PortletBag;
031    import com.liferay.portal.kernel.scheduler.SchedulerEngineUtil;
032    import com.liferay.portal.kernel.scheduler.SchedulerEntry;
033    import com.liferay.portal.kernel.scheduler.StorageType;
034    import com.liferay.portal.kernel.search.Indexer;
035    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
036    import com.liferay.portal.kernel.servlet.DirectServletRegistry;
037    import com.liferay.portal.kernel.servlet.FileTimestampUtil;
038    import com.liferay.portal.kernel.servlet.PortletServlet;
039    import com.liferay.portal.kernel.servlet.ServletContextPool;
040    import com.liferay.portal.kernel.servlet.ServletContextProvider;
041    import com.liferay.portal.kernel.util.ClassUtil;
042    import com.liferay.portal.kernel.util.GetterUtil;
043    import com.liferay.portal.kernel.util.HttpUtil;
044    import com.liferay.portal.kernel.util.LocaleUtil;
045    import com.liferay.portal.kernel.util.ObjectValuePair;
046    import com.liferay.portal.kernel.util.PropsKeys;
047    import com.liferay.portal.kernel.util.StringUtil;
048    import com.liferay.portal.kernel.util.Validator;
049    import com.liferay.portal.kernel.webdav.WebDAVUtil;
050    import com.liferay.portal.kernel.workflow.WorkflowHandler;
051    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
052    import com.liferay.portal.model.Portlet;
053    import com.liferay.portal.model.PortletApp;
054    import com.liferay.portal.model.PortletCategory;
055    import com.liferay.portal.model.PortletFilter;
056    import com.liferay.portal.model.PortletURLListener;
057    import com.liferay.portal.poller.PollerProcessorUtil;
058    import com.liferay.portal.pop.POPServerUtil;
059    import com.liferay.portal.security.permission.ResourceActionsUtil;
060    import com.liferay.portal.service.PortletLocalServiceUtil;
061    import com.liferay.portal.service.ResourceActionLocalServiceUtil;
062    import com.liferay.portal.service.ResourceCodeLocalServiceUtil;
063    import com.liferay.portal.spring.context.PortletContextLoader;
064    import com.liferay.portal.spring.context.PortletContextLoaderListener;
065    import com.liferay.portal.util.Portal;
066    import com.liferay.portal.util.PortalInstances;
067    import com.liferay.portal.util.PropsValues;
068    import com.liferay.portal.util.WebAppPool;
069    import com.liferay.portal.util.WebKeys;
070    import com.liferay.portal.xmlrpc.XmlRpcServlet;
071    import com.liferay.portlet.CustomUserAttributes;
072    import com.liferay.portlet.InvokerPortlet;
073    import com.liferay.portlet.PortletBagFactory;
074    import com.liferay.portlet.PortletContextBag;
075    import com.liferay.portlet.PortletContextBagPool;
076    import com.liferay.portlet.PortletFilterFactory;
077    import com.liferay.portlet.PortletInstanceFactoryUtil;
078    import com.liferay.portlet.PortletResourceBundles;
079    import com.liferay.portlet.PortletURLListenerFactory;
080    import com.liferay.portlet.asset.AssetRendererFactoryRegistryUtil;
081    import com.liferay.portlet.asset.model.AssetRendererFactory;
082    import com.liferay.portlet.social.service.SocialActivityInterpreterLocalServiceUtil;
083    import com.liferay.portlet.social.service.SocialRequestInterpreterLocalServiceUtil;
084    import com.liferay.util.log4j.Log4JUtil;
085    
086    import java.util.HashMap;
087    import java.util.HashSet;
088    import java.util.Iterator;
089    import java.util.List;
090    import java.util.Locale;
091    import java.util.Map;
092    import java.util.Properties;
093    import java.util.ResourceBundle;
094    import java.util.Set;
095    import java.util.concurrent.locks.Lock;
096    
097    import javax.portlet.PortletURLGenerationListener;
098    
099    import javax.servlet.ServletContext;
100    
101    import org.apache.portals.bridges.struts.StrutsPortlet;
102    
103    /**
104     * @author Brian Wing Shun Chan
105     * @author Brian Myunghun Kim
106     * @author Ivica Cardic
107     * @author Raymond Augé
108     */
109    public class PortletHotDeployListener extends BaseHotDeployListener {
110    
111            public void invokeDeploy(HotDeployEvent hotDeployEvent)
112                    throws HotDeployException {
113    
114                    try {
115                            doInvokeDeploy(hotDeployEvent);
116                    }
117                    catch (Throwable t) {
118                            throwHotDeployException(
119                                    hotDeployEvent, "Error registering portlets for ", t);
120                    }
121            }
122    
123            public void invokeUndeploy(HotDeployEvent hotDeployEvent)
124                    throws HotDeployException {
125    
126                    try {
127                            doInvokeUndeploy(hotDeployEvent);
128                    }
129                    catch (Throwable t) {
130                            throwHotDeployException(
131                                    hotDeployEvent, "Error unregistering portlets for ", t);
132                    }
133            }
134    
135            protected void destroyPortlet(Portlet portlet, Set<String> portletIds)
136                    throws Exception {
137    
138                    PortletApp portletApp = portlet.getPortletApp();
139    
140                    Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
141    
142                    for (PortletFilter portletFilter : portletFilters) {
143                            PortletFilterFactory.destroy(portletFilter);
144                    }
145    
146                    Set<PortletURLListener> portletURLListeners =
147                            portletApp.getPortletURLListeners();
148    
149                    for (PortletURLListener portletURLListener : portletURLListeners) {
150                            PortletURLListenerFactory.destroy(portletURLListener);
151                    }
152    
153                    List<Indexer> indexers = portlet.getIndexerInstances();
154    
155                    for (Indexer indexer : indexers) {
156                            IndexerRegistryUtil.unregister(indexer);
157                    }
158    
159                    if (PropsValues.SCHEDULER_ENABLED) {
160                            List<SchedulerEntry> schedulerEntries =
161                                    portlet.getSchedulerEntries();
162    
163                            if ((schedulerEntries != null) && !schedulerEntries.isEmpty()) {
164                                    for (SchedulerEntry schedulerEntry : schedulerEntries) {
165                                            SchedulerEngineUtil.unschedule(
166                                                    schedulerEntry, StorageType.MEMORY_CLUSTERED);
167                                    }
168                            }
169                    }
170    
171                    PollerProcessorUtil.deletePollerProcessor(portlet.getPortletId());
172    
173                    POPServerUtil.deleteListener(portlet.getPopMessageListenerInstance());
174    
175                    SocialActivityInterpreterLocalServiceUtil.deleteActivityInterpreter(
176                            portlet.getSocialActivityInterpreterInstance());
177    
178                    SocialRequestInterpreterLocalServiceUtil.deleteRequestInterpreter(
179                            portlet.getSocialRequestInterpreterInstance());
180    
181                    WebDAVUtil.deleteStorage(portlet.getWebDAVStorageInstance());
182    
183                    XmlRpcServlet.unregisterMethod(portlet.getXmlRpcMethodInstance());
184    
185                    List<AssetRendererFactory> assetRendererFactories =
186                            portlet.getAssetRendererFactoryInstances();
187    
188                    if (assetRendererFactories != null) {
189                            AssetRendererFactoryRegistryUtil.unregister(assetRendererFactories);
190                    }
191    
192                    List<AtomCollectionAdapter<?>> atomCollectionAdapters =
193                            portlet.getAtomCollectionAdapterInstances();
194    
195                    if (atomCollectionAdapters != null) {
196                            AtomCollectionAdapterRegistryUtil.unregister(
197                                    atomCollectionAdapters);
198                    }
199    
200                    List<WorkflowHandler> workflowHandlers =
201                            portlet.getWorkflowHandlerInstances();
202    
203                    if (workflowHandlers != null) {
204                            WorkflowHandlerRegistryUtil.unregister(workflowHandlers);
205                    }
206    
207                    PortletInstanceFactoryUtil.destroy(portlet);
208    
209                    portletIds.add(portlet.getPortletId());
210            }
211    
212            protected void doInvokeDeploy(HotDeployEvent hotDeployEvent)
213                    throws Exception {
214    
215                    // Servlet context
216    
217                    ServletContext servletContext = hotDeployEvent.getServletContext();
218    
219                    String servletContextName = servletContext.getServletContextName();
220    
221                    if (_log.isDebugEnabled()) {
222                            _log.debug("Invoking deploy for " + servletContextName);
223                    }
224    
225                    // Spring initialization lock
226    
227                    String configLocation = servletContext.getInitParameter(
228                            PortletContextLoader.PORTAL_CONFIG_LOCATION_PARAM);
229    
230                    Properties serviceBuilderProperties =
231                            (Properties)servletContext.getAttribute(
232                                    PluginPackageHotDeployListener.SERVICE_BUILDER_PROPERTIES);
233    
234                    if (Validator.isNotNull(configLocation) ||
235                            (serviceBuilderProperties != null)) {
236    
237                            String lockKey = PortletContextLoaderListener.getLockKey(
238                                    servletContext);
239    
240                            Lock lock = LockRegistry.allocateLock(lockKey, lockKey);
241    
242                            lock.lock();
243                    }
244    
245                    // Company ids
246    
247                    long[] companyIds = PortalInstances.getCompanyIds();
248    
249                    // Initialize portlets
250    
251                    String[] xmls = new String[] {
252                            HttpUtil.URLtoString(
253                                    servletContext.getResource(
254                                            "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_STANDARD)),
255                            HttpUtil.URLtoString(
256                                    servletContext.getResource(
257                                            "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_CUSTOM)),
258                            HttpUtil.URLtoString(
259                                    servletContext.getResource("/WEB-INF/liferay-portlet.xml")),
260                            HttpUtil.URLtoString(servletContext.getResource("/WEB-INF/web.xml"))
261                    };
262    
263                    if ((xmls[0] == null) && (xmls[1] == null)) {
264                            return;
265                    }
266    
267                    logRegistration(servletContextName);
268    
269                    List<Portlet> portlets = PortletLocalServiceUtil.initWAR(
270                            servletContextName, servletContext, xmls,
271                            hotDeployEvent.getPluginPackage());
272    
273                    // Class loader
274    
275                    ClassLoader portletClassLoader = hotDeployEvent.getContextClassLoader();
276    
277                    servletContext.setAttribute(
278                            PortletServlet.PORTLET_CLASS_LOADER, portletClassLoader);
279    
280                    // Logger
281    
282                    initLogger(portletClassLoader);
283    
284                    // Portlet context wrapper
285    
286                    _portletAppInitialized = false;
287                    _strutsBridges = false;
288    
289                    PortletBagFactory portletBagFactory = new PortletBagFactory();
290    
291                    portletBagFactory.setClassLoader(portletClassLoader);
292                    portletBagFactory.setServletContext(servletContext);
293                    portletBagFactory.setWARFile(true);
294    
295                    Iterator<Portlet> itr = portlets.iterator();
296    
297                    while (itr.hasNext()) {
298                            Portlet portlet = itr.next();
299    
300                            PortletBag portletBag = initPortlet(portlet, portletBagFactory);
301    
302                            if (portletBag == null) {
303                                    itr.remove();
304                            }
305                            else {
306                                    if (!_portletAppInitialized) {
307                                            initPortletApp(
308                                                    portlet, servletContextName, servletContext,
309                                                    portletClassLoader);
310    
311                                            _portletAppInitialized = true;
312                                    }
313                            }
314                    }
315    
316                    // Struts bridges
317    
318                    if (!_strutsBridges) {
319                            _strutsBridges = GetterUtil.getBoolean(
320                                    servletContext.getInitParameter(
321                                            "struts-bridges-context-provider"));
322                    }
323    
324                    if (_strutsBridges) {
325                            servletContext.setAttribute(
326                                    ServletContextProvider.STRUTS_BRIDGES_CONTEXT_PROVIDER,
327                                    new LiferayServletContextProvider());
328                    }
329    
330                    // Portlet display
331    
332                    String xml = HttpUtil.URLtoString(
333                            servletContext.getResource("/WEB-INF/liferay-display.xml"));
334    
335                    PortletCategory newPortletCategory =
336                            PortletLocalServiceUtil.getWARDisplay(servletContextName, xml);
337    
338                    for (long companyId : companyIds) {
339                            PortletCategory portletCategory = (PortletCategory)WebAppPool.get(
340                                    companyId, WebKeys.PORTLET_CATEGORY);
341    
342                            if (portletCategory != null) {
343                                    portletCategory.merge(newPortletCategory);
344                            }
345                            else {
346                                    _log.error(
347                                            "Unable to register portlet for company " + companyId +
348                                                    " because it does not exist");
349                            }
350                    }
351    
352                    // Portlet properties
353    
354                    processPortletProperties(servletContextName, portletClassLoader);
355    
356                    // Resource actions, resource codes, and check
357    
358                    itr = portlets.iterator();
359    
360                    while (itr.hasNext()) {
361                            Portlet portlet = itr.next();
362    
363                            List<String> modelNames =
364                                    ResourceActionsUtil.getPortletModelResources(
365                                            portlet.getPortletId());
366    
367                            for (long companyId : companyIds) {
368                                    ResourceCodeLocalServiceUtil.checkResourceCodes(
369                                            companyId, portlet.getPortletId());
370    
371                                    for (String modelName : modelNames) {
372                                            ResourceCodeLocalServiceUtil.checkResourceCodes(
373                                                    companyId, modelName);
374                                    }
375                            }
376    
377                            List<String> portletActions =
378                                    ResourceActionsUtil.getPortletResourceActions(
379                                            portlet.getPortletId());
380    
381                            ResourceActionLocalServiceUtil.checkResourceActions(
382                                    portlet.getPortletId(), portletActions);
383    
384                            for (String modelName : modelNames) {
385                                    List<String> modelActions =
386                                            ResourceActionsUtil.getModelResourceActions(modelName);
387    
388                                    ResourceActionLocalServiceUtil.checkResourceActions(
389                                            modelName, modelActions);
390                            }
391    
392                            for (long companyId : companyIds) {
393                                    Portlet curPortlet = PortletLocalServiceUtil.getPortletById(
394                                            companyId, portlet.getPortletId());
395    
396                                    PortletLocalServiceUtil.checkPortlet(curPortlet);
397                            }
398                    }
399    
400                    // Ready
401    
402                    for (Portlet portlet : portlets) {
403                            boolean ready = GetterUtil.getBoolean(
404                                    servletContext.getInitParameter(
405                                            "portlets-ready-by-default"), true);
406    
407                            portlet.setReady(ready);
408                    }
409    
410                    // ClpMessageListener
411    
412                    registerClpMessageListeners(servletContext, portletClassLoader);
413    
414                    // Javadoc
415    
416                    JavadocManagerUtil.load(servletContextName, portletClassLoader);
417    
418                    // Clear cache
419    
420                    DirectServletRegistry.clearServlets();
421                    FileTimestampUtil.reset();
422    
423                    // Variables
424    
425                    _vars.put(
426                            servletContextName,
427                            new ObjectValuePair<long[], List<Portlet>>(companyIds, portlets));
428    
429                    if (_log.isInfoEnabled()) {
430                            if (portlets.size() == 1) {
431                                    _log.info(
432                                            "1 portlet for " + servletContextName +
433                                                    " is available for use");
434                            }
435                            else {
436                                    _log.info(
437                                            portlets.size() + " portlets for " + servletContextName +
438                                                    " are available for use");
439                            }
440                    }
441            }
442    
443            protected void doInvokeUndeploy(HotDeployEvent hotDeployEvent)
444                    throws Exception {
445    
446                    ServletContext servletContext = hotDeployEvent.getServletContext();
447    
448                    String servletContextName = servletContext.getServletContextName();
449    
450                    if (_log.isDebugEnabled()) {
451                            _log.debug("Invoking undeploy for " + servletContextName);
452                    }
453    
454                    ObjectValuePair<long[], List<Portlet>> ovp = _vars.remove(
455                            servletContextName);
456    
457                    if (ovp == null) {
458                            return;
459                    }
460    
461                    long[] companyIds = ovp.getKey();
462                    List<Portlet> portlets = ovp.getValue();
463    
464                    Set<String> portletIds = new HashSet<String>();
465    
466                    if (portlets != null) {
467                            if (_log.isInfoEnabled()) {
468                                    _log.info("Unregistering portlets for " + servletContextName);
469                            }
470    
471                            Iterator<Portlet> itr = portlets.iterator();
472    
473                            while (itr.hasNext()) {
474                                    Portlet portlet = itr.next();
475    
476                                    destroyPortlet(portlet, portletIds);
477                            }
478                    }
479    
480                    ServletContextPool.remove(servletContextName);
481    
482                    if (portletIds.size() > 0) {
483                            for (long companyId : companyIds) {
484                                    PortletCategory portletCategory =
485                                            (PortletCategory)WebAppPool.get(
486                                                    companyId, WebKeys.PORTLET_CATEGORY);
487    
488                                    portletCategory.separate(portletIds);
489                            }
490                    }
491    
492                    PortletContextBagPool.remove(servletContextName);
493                    PortletResourceBundles.remove(servletContextName);
494    
495                    unregisterClpMessageListeners(servletContext);
496    
497                    JavadocManagerUtil.unload(servletContextName);
498    
499                    if (_log.isInfoEnabled()) {
500                            if (portlets.size() == 1) {
501                                    _log.info(
502                                            "1 portlet for " + servletContextName +
503                                                    " was unregistered");
504                            }
505                            else {
506                                    _log.info(
507                                            portlets.size() + " portlets for " + servletContextName +
508                                                    " was unregistered");
509                            }
510                    }
511            }
512    
513            protected void initLogger(ClassLoader portletClassLoader) {
514                    Log4JUtil.configureLog4J(
515                            portletClassLoader.getResource("META-INF/portal-log4j.xml"));
516            }
517    
518            protected PortletBag initPortlet(
519                            Portlet portlet, PortletBagFactory portletBagFactory)
520                    throws Exception {
521    
522                    PortletBag portletBag = portletBagFactory.create(portlet);
523    
524                    if (portletBag == null) {
525                            return null;
526                    }
527    
528                    javax.portlet.Portlet portletInstance = portletBag.getPortletInstance();
529    
530                    if (ClassUtil.isSubclass(
531                                    portletInstance.getClass(), StrutsPortlet.class.getName())) {
532    
533                            _strutsBridges = true;
534                    }
535    
536                    return portletBag;
537            }
538    
539            protected void initPortletApp(
540                            Portlet portlet, String servletContextName,
541                            ServletContext servletContext, ClassLoader portletClassLoader)
542                    throws Exception {
543    
544                    PortletContextBag portletContextBag = new PortletContextBag(
545                            servletContextName);
546    
547                    PortletContextBagPool.put(servletContextName, portletContextBag);
548    
549                    PortletApp portletApp = portlet.getPortletApp();
550    
551                    servletContext.setAttribute(PortletServlet.PORTLET_APP, portletApp);
552    
553                    Map<String, String> customUserAttributes =
554                            portletApp.getCustomUserAttributes();
555    
556                    for (Map.Entry<String, String> entry :
557                                    customUserAttributes.entrySet()) {
558    
559                            String attrCustomClass = entry.getValue();
560    
561                            CustomUserAttributes customUserAttributesInstance =
562                                    (CustomUserAttributes)portletClassLoader.loadClass(
563                                            attrCustomClass).newInstance();
564    
565                            portletContextBag.getCustomUserAttributes().put(
566                                    attrCustomClass, customUserAttributesInstance);
567                    }
568    
569                    Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
570    
571                    for (PortletFilter portletFilter : portletFilters) {
572                            javax.portlet.filter.PortletFilter portletFilterInstance =
573                                    (javax.portlet.filter.PortletFilter)newInstance(
574                                            portletClassLoader,
575                                            new Class<?>[] {
576                                                    javax.portlet.filter.ActionFilter.class,
577                                                    javax.portlet.filter.EventFilter.class,
578                                                    javax.portlet.filter.PortletFilter.class,
579                                                    javax.portlet.filter.RenderFilter.class,
580                                                    javax.portlet.filter.ResourceFilter.class
581                                            },
582                                            portletFilter.getFilterClass());
583    
584                            portletContextBag.getPortletFilters().put(
585                                    portletFilter.getFilterName(), portletFilterInstance);
586                    }
587    
588                    InvokerPortlet invokerPortlet = PortletInstanceFactoryUtil.create(
589                            portlet, servletContext);
590    
591                    invokerPortlet.setPortletFilters();
592    
593                    Set<PortletURLListener> portletURLListeners =
594                            portletApp.getPortletURLListeners();
595    
596                    for (PortletURLListener portletURLListener : portletURLListeners) {
597                            PortletURLGenerationListener portletURLListenerInstance =
598                                    (PortletURLGenerationListener)newInstance(
599                                            portletClassLoader, PortletURLGenerationListener.class,
600                                            portletURLListener.getListenerClass());
601    
602                            portletContextBag.getPortletURLListeners().put(
603                                    portletURLListener.getListenerClass(),
604                                    portletURLListenerInstance);
605    
606                            PortletURLListenerFactory.create(portletURLListener);
607                    }
608            }
609    
610            protected void logRegistration(String servletContextName) {
611                    if (_log.isInfoEnabled()) {
612                            _log.info("Registering portlets for " + servletContextName);
613                    }
614            }
615    
616            protected void processPortletProperties(
617                            String servletContextName, ClassLoader portletClassLoader)
618                    throws Exception {
619    
620                    Configuration portletPropertiesConfiguration = null;
621    
622                    try {
623                            portletPropertiesConfiguration =
624                                    ConfigurationFactoryUtil.getConfiguration(
625                                            portletClassLoader, "portlet");
626                    }
627                    catch (Exception e) {
628                            if (_log.isDebugEnabled()) {
629                                    _log.debug("Unable to read portlet.properties");
630                            }
631    
632                            return;
633                    }
634    
635                    Properties portletProperties =
636                            portletPropertiesConfiguration.getProperties();
637    
638                    if (portletProperties.size() == 0) {
639                            return;
640                    }
641    
642                    String languageBundleName = portletProperties.getProperty(
643                            "language.bundle");
644    
645                    if (Validator.isNotNull(languageBundleName)) {
646                            Locale[] locales = LanguageUtil.getAvailableLocales();
647    
648                            for (Locale locale : locales) {
649                                    ResourceBundle resourceBundle = ResourceBundle.getBundle(
650                                            languageBundleName, locale, portletClassLoader);
651    
652                                    PortletResourceBundles.put(
653                                            servletContextName, LocaleUtil.toLanguageId(locale),
654                                            resourceBundle);
655                            }
656                    }
657    
658                    String[] resourceActionConfigs = StringUtil.split(
659                            portletProperties.getProperty(PropsKeys.RESOURCE_ACTIONS_CONFIGS));
660    
661                    for (String resourceActionConfig : resourceActionConfigs) {
662                            ResourceActionsUtil.read(
663                                    servletContextName, portletClassLoader, resourceActionConfig);
664                    }
665            }
666    
667            private static Log _log = LogFactoryUtil.getLog(
668                    PortletHotDeployListener.class);
669    
670            private static Map<String, ObjectValuePair<long[], List<Portlet>>> _vars =
671                    new HashMap<String, ObjectValuePair<long[], List<Portlet>>>();
672    
673            private boolean _portletAppInitialized;
674            private boolean _strutsBridges;
675    
676    }