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