001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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>>(
423                                    companyIds, portlets));
424    
425                    if (_log.isInfoEnabled()) {
426                            if (portlets.size() == 1) {
427                                    _log.info(
428                                            "1 portlet for " + servletContextName +
429                                                    " is available for use");
430                            }
431                            else {
432                                    _log.info(
433                                            portlets.size() + " portlets for " + servletContextName +
434                                                    " are available for use");
435                            }
436                    }
437            }
438    
439            protected void doInvokeUndeploy(HotDeployEvent hotDeployEvent)
440                    throws Exception {
441    
442                    ServletContext servletContext = hotDeployEvent.getServletContext();
443    
444                    String servletContextName = servletContext.getServletContextName();
445    
446                    if (_log.isDebugEnabled()) {
447                            _log.debug("Invoking undeploy for " + servletContextName);
448                    }
449    
450                    ObjectValuePair<long[], List<Portlet>> ovp =
451                            _vars.remove(servletContextName);
452    
453                    if (ovp == null) {
454                            return;
455                    }
456    
457                    long[] companyIds = ovp.getKey();
458                    List<Portlet> portlets = ovp.getValue();
459    
460                    Set<String> portletIds = new HashSet<String>();
461    
462                    if (portlets != null) {
463                            if (_log.isInfoEnabled()) {
464                                    _log.info(
465                                            "Unregistering portlets for " + servletContextName);
466                            }
467    
468                            Iterator<Portlet> itr = portlets.iterator();
469    
470                            while (itr.hasNext()) {
471                                    Portlet portlet = itr.next();
472    
473                                    destroyPortlet(portlet, portletIds);
474                            }
475                    }
476    
477                    ServletContextPool.remove(servletContextName);
478    
479                    if (portletIds.size() > 0) {
480                            for (long companyId : companyIds) {
481                                    PortletCategory portletCategory =
482                                            (PortletCategory)WebAppPool.get(
483                                                    companyId, WebKeys.PORTLET_CATEGORY);
484    
485                                    portletCategory.separate(portletIds);
486                            }
487                    }
488    
489                    PortletContextBagPool.remove(servletContextName);
490                    PortletResourceBundles.remove(servletContextName);
491    
492                    unregisterClpMessageListeners(servletContext);
493    
494                    if (_log.isInfoEnabled()) {
495                            if (portlets.size() == 1) {
496                                    _log.info(
497                                            "1 portlet for " + servletContextName +
498                                                    " was unregistered");
499                            }
500                            else {
501                                    _log.info(
502                                            portlets.size() + " portlets for " + servletContextName +
503                                                    " was unregistered");
504                            }
505                    }
506            }
507    
508            protected void initLogger(ClassLoader portletClassLoader) {
509                    Log4JUtil.configureLog4J(
510                            portletClassLoader.getResource("META-INF/portal-log4j.xml"));
511            }
512    
513            protected PortletBag initPortlet(
514                            Portlet portlet, PortletBagFactory portletBagFactory)
515                    throws Exception {
516    
517                    PortletBag portletBag = portletBagFactory.create(portlet);
518    
519                    if (portletBag == null) {
520                            return null;
521                    }
522    
523                    javax.portlet.Portlet portletInstance = portletBag.getPortletInstance();
524    
525                    if (ClassUtil.isSubclass(
526                                    portletInstance.getClass(), StrutsPortlet.class.getName())) {
527    
528                            _strutsBridges = true;
529                    }
530    
531                    return portletBag;
532            }
533    
534            protected void initPortletApp(
535                            Portlet portlet, String servletContextName,
536                            ServletContext servletContext, ClassLoader portletClassLoader)
537                    throws Exception {
538    
539                    PortletContextBag portletContextBag = new PortletContextBag(
540                            servletContextName);
541    
542                    PortletContextBagPool.put(servletContextName, portletContextBag);
543    
544                    PortletApp portletApp = portlet.getPortletApp();
545    
546                    servletContext.setAttribute(PortletServlet.PORTLET_APP, portletApp);
547    
548                    Map<String, String> customUserAttributes =
549                            portletApp.getCustomUserAttributes();
550    
551                    for (Map.Entry<String, String> entry :
552                                    customUserAttributes.entrySet()) {
553    
554                            String attrCustomClass = entry.getValue();
555    
556                            CustomUserAttributes customUserAttributesInstance =
557                                    (CustomUserAttributes)portletClassLoader.loadClass(
558                                            attrCustomClass).newInstance();
559    
560                            portletContextBag.getCustomUserAttributes().put(
561                                    attrCustomClass, customUserAttributesInstance);
562                    }
563    
564                    Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
565    
566                    for (PortletFilter portletFilter : portletFilters) {
567                            javax.portlet.filter.PortletFilter portletFilterInstance =
568                                    (javax.portlet.filter.PortletFilter)newInstance(
569                                            portletClassLoader,
570                                            new Class<?>[] {
571                                                    javax.portlet.filter.ActionFilter.class,
572                                                    javax.portlet.filter.EventFilter.class,
573                                                    javax.portlet.filter.PortletFilter.class,
574                                                    javax.portlet.filter.RenderFilter.class,
575                                                    javax.portlet.filter.ResourceFilter.class
576                                            },
577                                            portletFilter.getFilterClass());
578    
579                            portletContextBag.getPortletFilters().put(
580                                    portletFilter.getFilterName(), portletFilterInstance);
581                    }
582    
583                    InvokerPortlet invokerPortlet = PortletInstanceFactoryUtil.create(
584                            portlet, servletContext);
585    
586                    invokerPortlet.setPortletFilters();
587    
588                    Set<PortletURLListener> portletURLListeners =
589                            portletApp.getPortletURLListeners();
590    
591                    for (PortletURLListener portletURLListener : portletURLListeners) {
592                            PortletURLGenerationListener portletURLListenerInstance =
593                                    (PortletURLGenerationListener)newInstance(
594                                            portletClassLoader, PortletURLGenerationListener.class,
595                                            portletURLListener.getListenerClass());
596    
597                            portletContextBag.getPortletURLListeners().put(
598                                    portletURLListener.getListenerClass(),
599                                    portletURLListenerInstance);
600    
601                            PortletURLListenerFactory.create(portletURLListener);
602                    }
603            }
604    
605            protected void logRegistration(String servletContextName) {
606                    if (_log.isInfoEnabled()) {
607                            _log.info("Registering portlets for " + servletContextName);
608                    }
609            }
610    
611            protected void processPortletProperties(
612                            String servletContextName, ClassLoader portletClassLoader)
613                    throws Exception {
614    
615                    Configuration portletPropertiesConfiguration = null;
616    
617                    try {
618                            portletPropertiesConfiguration =
619                                    ConfigurationFactoryUtil.getConfiguration(
620                                            portletClassLoader, "portlet");
621                    }
622                    catch (Exception e) {
623                            if (_log.isDebugEnabled()) {
624                                    _log.debug("Unable to read portlet.properties");
625                            }
626    
627                            return;
628                    }
629    
630                    Properties portletProperties =
631                            portletPropertiesConfiguration.getProperties();
632    
633                    if (portletProperties.size() == 0) {
634                            return;
635                    }
636    
637                    String languageBundleName = portletProperties.getProperty(
638                            "language.bundle");
639    
640                    if (Validator.isNotNull(languageBundleName)) {
641                            Locale[] locales = LanguageUtil.getAvailableLocales();
642    
643                            for (Locale locale : locales) {
644                                    ResourceBundle resourceBundle = ResourceBundle.getBundle(
645                                            languageBundleName, locale, portletClassLoader);
646    
647                                    PortletResourceBundles.put(
648                                            servletContextName, LocaleUtil.toLanguageId(locale),
649                                            resourceBundle);
650                            }
651                    }
652    
653                    String[] resourceActionConfigs = StringUtil.split(
654                            portletProperties.getProperty(PropsKeys.RESOURCE_ACTIONS_CONFIGS));
655    
656                    for (String resourceActionConfig : resourceActionConfigs) {
657                            ResourceActionsUtil.read(
658                                    servletContextName, portletClassLoader, resourceActionConfig);
659                    }
660            }
661    
662            private static Log _log = LogFactoryUtil.getLog(
663                    PortletHotDeployListener.class);
664    
665            private static Map<String, ObjectValuePair<long[], List<Portlet>>> _vars =
666                    new HashMap<String, ObjectValuePair<long[], List<Portlet>>>();
667    
668            private boolean _portletAppInitialized;
669            private boolean _strutsBridges;
670    
671    }