001    /**
002     * Copyright (c) 2000-2010 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.service.impl;
016    
017    import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
018    import com.liferay.portal.kernel.cache.PortalCache;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.image.SpriteProcessorUtil;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.plugin.PluginPackage;
025    import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
026    import com.liferay.portal.kernel.portlet.LiferayPortletConfig;
027    import com.liferay.portal.kernel.portlet.LiferayWindowState;
028    import com.liferay.portal.kernel.scheduler.SchedulerEntry;
029    import com.liferay.portal.kernel.scheduler.SchedulerEntryImpl;
030    import com.liferay.portal.kernel.scheduler.TimeUnit;
031    import com.liferay.portal.kernel.scheduler.TriggerType;
032    import com.liferay.portal.kernel.servlet.ServletContextUtil;
033    import com.liferay.portal.kernel.util.ContentTypes;
034    import com.liferay.portal.kernel.util.GetterUtil;
035    import com.liferay.portal.kernel.util.ListUtil;
036    import com.liferay.portal.kernel.util.ServerDetector;
037    import com.liferay.portal.kernel.util.StringPool;
038    import com.liferay.portal.kernel.util.Validator;
039    import com.liferay.portal.kernel.xml.Document;
040    import com.liferay.portal.kernel.xml.Element;
041    import com.liferay.portal.kernel.xml.QName;
042    import com.liferay.portal.kernel.xml.SAXReaderUtil;
043    import com.liferay.portal.model.CompanyConstants;
044    import com.liferay.portal.model.EventDefinition;
045    import com.liferay.portal.model.Portlet;
046    import com.liferay.portal.model.PortletApp;
047    import com.liferay.portal.model.PortletCategory;
048    import com.liferay.portal.model.PortletConstants;
049    import com.liferay.portal.model.PortletFilter;
050    import com.liferay.portal.model.PortletInfo;
051    import com.liferay.portal.model.PortletURLListener;
052    import com.liferay.portal.model.PublicRenderParameter;
053    import com.liferay.portal.model.ResourceConstants;
054    import com.liferay.portal.model.Role;
055    import com.liferay.portal.model.impl.EventDefinitionImpl;
056    import com.liferay.portal.model.impl.PortletAppImpl;
057    import com.liferay.portal.model.impl.PortletFilterImpl;
058    import com.liferay.portal.model.impl.PortletImpl;
059    import com.liferay.portal.model.impl.PortletURLListenerImpl;
060    import com.liferay.portal.model.impl.PublicRenderParameterImpl;
061    import com.liferay.portal.security.permission.ActionKeys;
062    import com.liferay.portal.security.permission.ResourceActionsUtil;
063    import com.liferay.portal.service.base.PortletLocalServiceBaseImpl;
064    import com.liferay.portal.util.ContentUtil;
065    import com.liferay.portal.util.PortalUtil;
066    import com.liferay.portal.util.PortletKeys;
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.portlet.PortletConfigFactoryUtil;
071    import com.liferay.portlet.PortletContextFactory;
072    import com.liferay.portlet.PortletInstanceFactoryUtil;
073    import com.liferay.portlet.PortletPreferencesSerializer;
074    import com.liferay.portlet.PortletQNameUtil;
075    import com.liferay.portlet.expando.model.CustomAttributesDisplay;
076    import com.liferay.util.bridges.mvc.MVCPortlet;
077    
078    import java.io.File;
079    
080    import java.util.ArrayList;
081    import java.util.HashMap;
082    import java.util.HashSet;
083    import java.util.Iterator;
084    import java.util.LinkedHashSet;
085    import java.util.List;
086    import java.util.Map;
087    import java.util.Properties;
088    import java.util.Set;
089    import java.util.concurrent.ConcurrentHashMap;
090    
091    import javax.portlet.PortletMode;
092    import javax.portlet.PreferencesValidator;
093    import javax.portlet.WindowState;
094    
095    import javax.servlet.ServletContext;
096    
097    /**
098     * @author Brian Wing Shun Chan
099     * @author Raymond Augé
100     * @author Eduardo Lundgren
101     * @author Wesley Gong
102     */
103    public class PortletLocalServiceImpl extends PortletLocalServiceBaseImpl {
104    
105            public void checkPortlet(Portlet portlet)
106                    throws PortalException, SystemException {
107    
108                    if (portlet.isSystem()) {
109                            return;
110                    }
111    
112                    String[] roleNames = portlet.getRolesArray();
113    
114                    if (roleNames.length == 0) {
115                            return;
116                    }
117    
118                    long companyId = portlet.getCompanyId();
119                    String name = portlet.getPortletId();
120                    int scope = ResourceConstants.SCOPE_COMPANY;
121                    String primKey = String.valueOf(companyId);
122                    String actionId = ActionKeys.ADD_TO_PAGE;
123    
124                    List<String> actionIds = ResourceActionsUtil.getPortletResourceActions(
125                            name);
126    
127                    if (actionIds.contains(actionId)) {
128                            for (String roleName : roleNames) {
129                                    Role role = roleLocalService.getRole(companyId, roleName);
130    
131                                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
132                                            resourcePermissionLocalService.addResourcePermission(
133                                                    companyId, name, scope, primKey, role.getRoleId(),
134                                                    actionId);
135                                    }
136                                    else {
137                                            permissionLocalService.setRolePermission(
138                                                    role.getRoleId(), companyId, name, scope, primKey,
139                                                    actionId);
140                                    }
141                            }
142                    }
143    
144                    updatePortlet(
145                            companyId, portlet.getPortletId(), StringPool.BLANK,
146                            portlet.isActive());
147            }
148    
149            public void checkPortlets(long companyId)
150                    throws PortalException, SystemException {
151    
152                    List<Portlet> portlets = getPortlets(companyId);
153    
154                    for (Portlet portlet : portlets) {
155                            checkPortlet(portlet);
156                    }
157            }
158    
159            public void clearCache() {
160    
161                    // Refresh security path to portlet id mapping for all portlets
162    
163                    _portletIdsByStrutsPath.clear();
164    
165                    // Refresh company portlets
166    
167                    _companyPortletsPool.removeAll();
168            }
169    
170            public Portlet clonePortlet(long companyId, String portletId)
171                    throws SystemException {
172    
173                    Portlet portlet = getPortletById(companyId, portletId);
174    
175                    return (Portlet)portlet.clone();
176            }
177    
178            public Portlet deployRemotePortlet(Portlet portlet, String categoryName)
179                    throws SystemException {
180    
181                    Map<String, Portlet> portletsPool = _getPortletsPool();
182    
183                    portletsPool.put(portlet.getPortletId(), portlet);
184    
185                    PortletInstanceFactoryUtil.clear(portlet, false);
186    
187                    PortletConfigFactoryUtil.destroy(portlet);
188                    PortletContextFactory.destroy(portlet);
189    
190                    clearCache();
191    
192                    PortletCategory newPortletCategory = new PortletCategory();
193    
194                    PortletCategory oldPortletCategory = new PortletCategory(categoryName);
195    
196                    newPortletCategory.addCategory(oldPortletCategory);
197    
198                    oldPortletCategory.getPortletIds().add(portlet.getPortletId());
199    
200                    long companyId = portlet.getCompanyId();
201    
202                    PortletCategory portletCategory = (PortletCategory)WebAppPool.get(
203                            String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
204    
205                    if (portletCategory != null) {
206                            portletCategory.merge(newPortletCategory);
207                    }
208                    else {
209                            _log.error(
210                                    "Unable to register remote portlet for company " + companyId +
211                                            " because it does not exist");
212                    }
213    
214                    List<String> portletActions =
215                            ResourceActionsUtil.getPortletResourceActions(
216                                    portlet.getPortletId());
217    
218                    resourceActionLocalService.checkResourceActions(
219                            portlet.getPortletId(), portletActions);
220    
221                    return portlet;
222            }
223    
224            public void destroyPortlet(Portlet portlet) {
225                    String portletId = portlet.getRootPortletId();
226    
227                    _friendlyURLMapperPortlets.remove(portletId);
228    
229                    Map<String, Portlet> portletsPool = _getPortletsPool();
230    
231                    portletsPool.remove(portletId);
232    
233                    PortletApp portletApp = portlet.getPortletApp();
234    
235                    if (portletApp != null) {
236                            _portletAppsPool.remove(portletApp.getServletContextName());
237                    }
238    
239                    clearCache();
240            }
241    
242            public void destroyRemotePortlet(Portlet portlet) {
243                    destroyPortlet(portlet);
244            }
245    
246            public List<CustomAttributesDisplay> getCustomAttributesDisplays() {
247                    List<CustomAttributesDisplay> customAttributesDisplays =
248                            new ArrayList<CustomAttributesDisplay>(
249                                    _customAttributesDisplayPortlets.size());
250    
251                    for (Map.Entry<String, Portlet> entry :
252                                    _customAttributesDisplayPortlets.entrySet()) {
253    
254                            Portlet portlet = entry.getValue();
255    
256                            List<CustomAttributesDisplay> portletCustomAttributesDisplays =
257                                    portlet.getCustomAttributesDisplayInstances();
258    
259                            if ((portletCustomAttributesDisplays != null) &&
260                                    (!portletCustomAttributesDisplays.isEmpty())) {
261    
262                                    customAttributesDisplays.addAll(
263                                            portletCustomAttributesDisplays);
264                            }
265                    }
266    
267                    return customAttributesDisplays;
268            }
269    
270            public PortletCategory getEARDisplay(String xml) throws SystemException {
271                    try {
272                            return _readLiferayDisplayXML(xml);
273                    }
274                    catch (Exception e) {
275                            throw new SystemException(e);
276                    }
277            }
278    
279            public List<Portlet> getFriendlyURLMapperPortlets() {
280                    List<Portlet> portlets = new ArrayList<Portlet>(
281                            _friendlyURLMapperPortlets.size());
282    
283                    for (Map.Entry<String, Portlet> entry :
284                                    _friendlyURLMapperPortlets.entrySet()) {
285    
286                            Portlet portlet = entry.getValue();
287    
288                            FriendlyURLMapper friendlyURLMapper =
289                                    portlet.getFriendlyURLMapperInstance();
290    
291                            if (friendlyURLMapper != null) {
292                                    portlets.add(portlet);
293                            }
294                    }
295    
296                    return portlets;
297            }
298    
299            public List<FriendlyURLMapper> getFriendlyURLMappers() {
300                    List<FriendlyURLMapper> friendlyURLMappers =
301                            new ArrayList<FriendlyURLMapper>(_friendlyURLMapperPortlets.size());
302    
303                    for (Map.Entry<String, Portlet> entry :
304                                    _friendlyURLMapperPortlets.entrySet()) {
305    
306                            Portlet portlet = entry.getValue();
307    
308                            FriendlyURLMapper friendlyURLMapper =
309                                    portlet.getFriendlyURLMapperInstance();
310    
311                            if (friendlyURLMapper != null) {
312                                    friendlyURLMappers.add(friendlyURLMapper);
313                            }
314                    }
315    
316                    return friendlyURLMappers;
317            }
318    
319            public PortletApp getPortletApp(String servletContextName) {
320                    return _getPortletApp(servletContextName);
321            }
322    
323            public Portlet getPortletById(long companyId, String portletId)
324                    throws SystemException {
325    
326                    portletId = PortalUtil.getJsSafePortletId(portletId);
327    
328                    Portlet portlet = null;
329    
330                    Map<String, Portlet> companyPortletsPool = _getPortletsPool(companyId);
331    
332                    String rootPortletId = PortletConstants.getRootPortletId(portletId);
333    
334                    if (portletId.equals(rootPortletId)) {
335                            portlet = companyPortletsPool.get(portletId);
336                    }
337                    else {
338                            portlet = companyPortletsPool.get(rootPortletId);
339    
340                            if (portlet != null) {
341                                    portlet = portlet.getClonedInstance(portletId);
342                            }
343                    }
344    
345                    if (portlet != null) {
346                            return portlet;
347                    }
348    
349                    if (portletId.equals(PortletKeys.LIFERAY_PORTAL)) {
350                            return portlet;
351                    }
352    
353                    if (_portletsPool.isEmpty()) {
354                            if (_log.isDebugEnabled()) {
355                                    _log.debug("No portlets are installed");
356                            }
357                    }
358                    else {
359                            if (_log.isInfoEnabled()) {
360                                    _log.info(
361                                            "Portlet not found for " + companyId + " " + portletId);
362                            }
363    
364                            portlet = new PortletImpl(CompanyConstants.SYSTEM, portletId);
365    
366                            portlet.setTimestamp(System.currentTimeMillis());
367    
368                            PortletApp portletApp = _getPortletApp(StringPool.BLANK);
369    
370                            portlet.setPortletApp(portletApp);
371    
372                            portlet.setPortletName(portletId);
373                            portlet.setDisplayName(portletId);
374                            portlet.setPortletClass(MVCPortlet.class.getName());
375    
376                            Map<String, String> initParams = portlet.getInitParams();
377    
378                            initParams.put("view-jsp", "/html/portal/undeployed_portlet.jsp");
379    
380                            Set<String> mimeTypePortletModes = new HashSet<String>();
381    
382                            mimeTypePortletModes.add(PortletMode.VIEW.toString().toLowerCase());
383    
384                            Map<String, Set<String>> portletModes = portlet.getPortletModes();
385    
386                            portletModes.put(ContentTypes.TEXT_HTML, mimeTypePortletModes);
387    
388                            Set<String> mimeTypeWindowStates = new HashSet<String>();
389    
390                            mimeTypeWindowStates.add(
391                                    WindowState.NORMAL.toString().toLowerCase());
392    
393                            Map<String, Set<String>> windowStates = portlet.getWindowStates();
394    
395                            windowStates.put(ContentTypes.TEXT_HTML, mimeTypeWindowStates);
396    
397                            portlet.setPortletInfo(
398                                    new PortletInfo(portletId, portletId, portletId, portletId));
399    
400                            if (PortletConstants.getInstanceId(portletId) != null) {
401                                    portlet.setInstanceable(true);
402                            }
403    
404                            portlet.setActive(true);
405                            portlet.setUndeployedPortlet(true);
406                    }
407    
408                    return portlet;
409            }
410    
411            public Portlet getPortletById(String portletId) {
412                    Map<String, Portlet> portletsPool = _getPortletsPool();
413    
414                    return portletsPool.get(portletId);
415            }
416    
417            public Portlet getPortletByStrutsPath(long companyId, String strutsPath)
418                    throws SystemException {
419    
420                    return getPortletById(companyId, _getPortletId(strutsPath));
421            }
422    
423            public List<Portlet> getPortlets() {
424                    Map<String, Portlet> portletsPool = _getPortletsPool();
425    
426                    return ListUtil.fromCollection(portletsPool.values());
427            }
428    
429            public List<Portlet> getPortlets(long companyId) throws SystemException {
430                    return getPortlets(companyId, true, true);
431            }
432    
433            public List<Portlet> getPortlets(
434                            long companyId, boolean showSystem, boolean showPortal)
435                    throws SystemException {
436    
437                    Map<String, Portlet> portletsPool = _getPortletsPool(companyId);
438    
439                    List<Portlet> portlets = ListUtil.fromCollection(portletsPool.values());
440    
441                    if (!showSystem || !showPortal) {
442                            Iterator<Portlet> itr = portlets.iterator();
443    
444                            while (itr.hasNext()) {
445                                    Portlet portlet = itr.next();
446    
447                                    if (showPortal &&
448                                            portlet.getPortletId().equals(PortletKeys.PORTAL)) {
449    
450                                    }
451                                    else if (!showPortal &&
452                                                     portlet.getPortletId().equals(PortletKeys.PORTAL)) {
453    
454                                            itr.remove();
455                                    }
456                                    else if (!showSystem && portlet.isSystem()) {
457                                            itr.remove();
458                                    }
459                            }
460                    }
461    
462                    return portlets;
463            }
464    
465            public PortletCategory getWARDisplay(String servletContextName, String xml)
466                    throws SystemException {
467    
468                    try {
469                            return _readLiferayDisplayXML(servletContextName, xml);
470                    }
471                    catch (Exception e) {
472                            throw new SystemException(e);
473                    }
474            }
475    
476            public boolean hasPortlet(long companyId, String portletId)
477                    throws SystemException {
478    
479                    portletId = PortalUtil.getJsSafePortletId(portletId);
480    
481                    Portlet portlet = null;
482    
483                    Map<String, Portlet> companyPortletsPool = _getPortletsPool(companyId);
484    
485                    String rootPortletId = PortletConstants.getRootPortletId(portletId);
486    
487                    if (portletId.equals(rootPortletId)) {
488                            portlet = companyPortletsPool.get(portletId);
489                    }
490                    else {
491                            portlet = companyPortletsPool.get(rootPortletId);
492                    }
493    
494                    if (portlet == null) {
495                            return false;
496                    }
497                    else {
498                            return true;
499                    }
500            }
501    
502            public void initEAR(
503                    ServletContext servletContext, String[] xmls,
504                    PluginPackage pluginPackage) {
505    
506                    // Clear pools every time initEAR is called. See LEP-5452.
507    
508                    _portletAppsPool.clear();
509                    _portletsPool.clear();
510                    _companyPortletsPool.removeAll();
511                    _portletIdsByStrutsPath.clear();
512                    _friendlyURLMapperPortlets.clear();
513    
514                    Map<String, Portlet> portletsPool = _getPortletsPool();
515    
516                    try {
517                            Set<String> servletURLPatterns = _readWebXML(xmls[4]);
518    
519                            Set<String> portletIds = _readPortletXML(
520                                    servletContext, xmls[0], portletsPool, servletURLPatterns,
521                                    pluginPackage);
522    
523                            portletIds.addAll(
524                                    _readPortletXML(
525                                            servletContext, xmls[1], portletsPool, servletURLPatterns,
526                                            pluginPackage));
527    
528                            Set<String> liferayPortletIds =
529                                    _readLiferayPortletXML(xmls[2], portletsPool);
530    
531                            liferayPortletIds.addAll(
532                                    _readLiferayPortletXML(xmls[3], portletsPool));
533    
534                            // Check for missing entries in liferay-portlet.xml
535    
536                            for (String portletId : portletIds) {
537                                    if (_log.isWarnEnabled() &&
538                                            !liferayPortletIds.contains(portletId)) {
539    
540                                            _log.warn(
541                                                    "Portlet with the name " + portletId +
542                                                            " is described in portlet.xml but does not " +
543                                                                    "have a matching entry in liferay-portlet.xml");
544                                    }
545                            }
546    
547                            // Check for missing entries in portlet.xml
548    
549                            for (String portletId : liferayPortletIds) {
550                                    if (_log.isWarnEnabled() && !portletIds.contains(portletId)) {
551                                            _log.warn(
552                                                    "Portlet with the name " + portletId +
553                                                            " is described in liferay-portlet.xml but does " +
554                                                                    "not have a matching entry in portlet.xml");
555                                    }
556                            }
557    
558                            // Remove portlets that should not be included
559    
560                            Iterator<Map.Entry<String, Portlet>> portletPoolsItr =
561                                    portletsPool.entrySet().iterator();
562    
563                            while (portletPoolsItr.hasNext()) {
564                                    Map.Entry<String, Portlet> entry = portletPoolsItr.next();
565    
566                                    Portlet portletModel = entry.getValue();
567    
568                                    if (!portletModel.getPortletId().equals(PortletKeys.ADMIN) &&
569                                            !portletModel.getPortletId().equals(
570                                                    PortletKeys.MY_ACCOUNT) &&
571                                            !portletModel.isInclude()) {
572    
573                                            portletPoolsItr.remove();
574                                    }
575                            }
576    
577                            // Sprite images
578    
579                            PortletApp portletApp = _getPortletApp(StringPool.BLANK);
580    
581                            _setSpriteImages(servletContext, portletApp, "/html/icons/");
582                    }
583                    catch (Exception e) {
584                            _log.error(e, e);
585                    }
586            }
587    
588            public List<Portlet> initWAR(
589                    String servletContextName, ServletContext servletContext, String[] xmls,
590                    PluginPackage pluginPackage) {
591    
592                    List<Portlet> portlets = new ArrayList<Portlet>();
593    
594                    Map<String, Portlet> portletsPool = _getPortletsPool();
595    
596                    try {
597                            Set<String> servletURLPatterns = _readWebXML(xmls[3]);
598    
599                            Set<String> portletIds = _readPortletXML(
600                                    servletContextName, servletContext, xmls[0], portletsPool,
601                                    servletURLPatterns, pluginPackage);
602    
603                            portletIds.addAll(
604                                    _readPortletXML(
605                                            servletContextName, servletContext, xmls[1], portletsPool,
606                                            servletURLPatterns, pluginPackage));
607    
608                            Set<String> liferayPortletIds = _readLiferayPortletXML(
609                                    servletContextName, xmls[2], portletsPool);
610    
611                            // Check for missing entries in liferay-portlet.xml
612    
613                            for (String portletId : portletIds) {
614                                    if (_log.isWarnEnabled() &&
615                                            !liferayPortletIds.contains(portletId)) {
616    
617                                            _log.warn(
618                                                    "Portlet with the name " + portletId +
619                                                            " is described in portlet.xml but does not " +
620                                                                    "have a matching entry in liferay-portlet.xml");
621                                    }
622                            }
623    
624                            // Check for missing entries in portlet.xml
625    
626                            for (String portletId : liferayPortletIds) {
627                                    if (_log.isWarnEnabled() && !portletIds.contains(portletId)) {
628                                            _log.warn(
629                                                    "Portlet with the name " + portletId +
630                                                            " is described in liferay-portlet.xml but does " +
631                                                                    "not have a matching entry in portlet.xml");
632                                    }
633                            }
634    
635                            // Return the new portlets
636    
637                            for (String portletId : portletIds) {
638                                    Portlet portlet = _getPortletsPool().get(portletId);
639    
640                                    portlets.add(portlet);
641    
642                                    PortletInstanceFactoryUtil.clear(portlet);
643    
644                                    PortletConfigFactoryUtil.destroy(portlet);
645                                    PortletContextFactory.destroy(portlet);
646                            }
647    
648                            // Sprite images
649    
650                            PortletApp portletApp = _getPortletApp(servletContextName);
651    
652                            _setSpriteImages(servletContext, portletApp, "/icons/");
653                    }
654                    catch (Exception e) {
655                            _log.error(e, e);
656                    }
657    
658                    clearCache();
659    
660                    return portlets;
661            }
662    
663            public Portlet updatePortlet(
664                            long companyId, String portletId, String roles, boolean active)
665                    throws SystemException {
666    
667                    portletId = PortalUtil.getJsSafePortletId(portletId);
668    
669                    Portlet portlet = portletPersistence.fetchByC_P(companyId, portletId);
670    
671                    if (portlet == null) {
672                            long id = counterLocalService.increment();
673    
674                            portlet = portletPersistence.create(id);
675    
676                            portlet.setCompanyId(companyId);
677                            portlet.setPortletId(portletId);
678                    }
679    
680                    portlet.setRoles(roles);
681                    portlet.setActive(active);
682    
683                    portletPersistence.update(portlet, false);
684    
685                    portlet = getPortletById(companyId, portletId);
686    
687                    portlet.setRoles(roles);
688                    portlet.setActive(active);
689    
690                    _updateCompanyPortletsPool(companyId);
691    
692                    return portlet;
693            }
694    
695            private String _encodeKey(long companyId) {
696                    return _keyPrefix.concat(String.valueOf(companyId));
697            }
698    
699            private PortletApp _getPortletApp(String servletContextName) {
700                    PortletApp portletApp = _portletAppsPool.get(servletContextName);
701    
702                    if (portletApp == null) {
703                            portletApp = new PortletAppImpl(servletContextName);
704    
705                            _portletAppsPool.put(servletContextName, portletApp);
706                    }
707    
708                    return portletApp;
709            }
710    
711            private String _getPortletId(String securityPath) {
712                    if (_portletIdsByStrutsPath.size() == 0) {
713                            for (Portlet portlet : _getPortletsPool().values()) {
714                                    _portletIdsByStrutsPath.put(
715                                            portlet.getStrutsPath(), portlet.getPortletId());
716                            }
717                    }
718    
719                    String portletId = _portletIdsByStrutsPath.get(securityPath);
720    
721                    if (Validator.isNull(portletId)) {
722                            _log.error(
723                                    "Struts path " + securityPath + " is not mapped to a portlet " +
724                                            "in liferay-portlet.xml");
725                    }
726    
727                    return portletId;
728            }
729    
730            private List<Portlet> _getPortletsByPortletName(
731                    String portletName, String servletContextName,
732                    Map<String, Portlet> portletsPool) {
733    
734                    List<Portlet> portlets = null;
735    
736                    int pos = portletName.indexOf(StringPool.STAR);
737    
738                    if (pos == -1) {
739                            portlets = new ArrayList<Portlet>();
740    
741                            String portletId = portletName;
742    
743                            if (Validator.isNotNull(servletContextName)) {
744                                    portletId =
745                                            portletId + PortletConstants.WAR_SEPARATOR +
746                                                    servletContextName;
747                            }
748    
749                            portletId = PortalUtil.getJsSafePortletId(portletId);
750    
751                            Portlet portlet = portletsPool.get(portletId);
752    
753                            if (portlet != null) {
754                                    portlets.add(portlet);
755                            }
756    
757                            return portlets;
758                    }
759    
760                    String portletNamePrefix = portletName.substring(0, pos);
761    
762                    portlets = _getPortletsByServletContextName(
763                            servletContextName, portletsPool);
764    
765                    Iterator<Portlet> itr = portlets.iterator();
766    
767                    while (itr.hasNext()) {
768                            Portlet portlet = itr.next();
769    
770                            String portletId = portlet.getPortletId();
771    
772                            if (!portletId.startsWith(portletNamePrefix)) {
773                                    itr.remove();
774                            }
775                    }
776    
777                    return portlets;
778            }
779    
780            private List<Portlet> _getPortletsByServletContextName(
781                    String servletContextName, Map<String, Portlet> portletsPool) {
782    
783                    List<Portlet> portlets = new ArrayList<Portlet>();
784    
785                    for (Map.Entry<String, Portlet> entry : portletsPool.entrySet()) {
786                            String portletId = entry.getKey();
787                            Portlet portlet = entry.getValue();
788    
789                            if (Validator.isNotNull(servletContextName)) {
790                                    if (portletId.endsWith(
791                                                    PortletConstants.WAR_SEPARATOR + servletContextName)) {
792    
793                                            portlets.add(portlet);
794                                    }
795                            }
796                            else {
797                                    if (!portletId.contains(PortletConstants.WAR_SEPARATOR)) {
798                                            portlets.add(portlet);
799                                    }
800                            }
801                    }
802    
803                    return portlets;
804            }
805    
806            private Map<String, Portlet> _getPortletsPool() {
807                    return _portletsPool;
808            }
809    
810            private Map<String, Portlet> _getPortletsPool(long companyId)
811                    throws SystemException {
812    
813                    String key = _encodeKey(companyId);
814    
815                    Map<String, Portlet> portletsPool =
816                            (Map<String, Portlet>)_companyPortletsPool.get(key);
817    
818                    if (portletsPool == null) {
819                            portletsPool = new ConcurrentHashMap<String, Portlet>();
820    
821                            Map<String, Portlet> parentPortletsPool = _getPortletsPool();
822    
823                            if (parentPortletsPool == null) {
824    
825                                    // The Upgrade scripts sometimes try to access portlet
826                                    // preferences before the portal's been initialized. Return an
827                                    // empty pool.
828    
829                                    return portletsPool;
830                            }
831    
832                            for (Portlet portlet : parentPortletsPool.values()) {
833                                    portlet = (Portlet)portlet.clone();
834    
835                                    portlet.setCompanyId(companyId);
836    
837                                    portletsPool.put(portlet.getPortletId(), portlet);
838                            }
839    
840                            List<Portlet> portlets = portletPersistence.findByCompanyId(
841                                    companyId);
842    
843                            for (Portlet portlet : portlets) {
844                                    Portlet portletModel = portletsPool.get(portlet.getPortletId());
845    
846                                    // Portlet may be null if it exists in the database but its
847                                    // portlet WAR is not yet loaded
848    
849                                    if (portletModel != null) {
850                                            portletModel.setPluginPackage(portlet.getPluginPackage());
851                                            portletModel.setDefaultPluginSetting(
852                                                    portlet.getDefaultPluginSetting());
853                                            portletModel.setRoles(portlet.getRoles());
854                                            portletModel.setActive(portlet.getActive());
855                                    }
856                            }
857    
858                            _companyPortletsPool.put(key, portletsPool);
859                    }
860    
861                    return portletsPool;
862            }
863    
864            private void _readLiferayDisplay(
865                    String servletContextName, Element element,
866                    PortletCategory portletCategory, Set<String> portletIds) {
867    
868                    for (Element categoryElement : element.elements("category")) {
869                            String name = categoryElement.attributeValue("name");
870    
871                            PortletCategory curPortletCategory = new PortletCategory(name);
872    
873                            portletCategory.addCategory(curPortletCategory);
874    
875                            Set<String> curPortletIds = curPortletCategory.getPortletIds();
876    
877                            for (Element portletElement : categoryElement.elements("portlet")) {
878                                    String portletId = portletElement.attributeValue("id");
879    
880                                    if (Validator.isNotNull(servletContextName)) {
881                                            portletId =
882                                                    portletId + PortletConstants.WAR_SEPARATOR +
883                                                            servletContextName;
884                                    }
885    
886                                    portletId = PortalUtil.getJsSafePortletId(portletId);
887    
888                                    portletIds.add(portletId);
889                                    curPortletIds.add(portletId);
890                            }
891    
892                            _readLiferayDisplay(
893                                    servletContextName, categoryElement, curPortletCategory,
894                                    portletIds);
895                    }
896            }
897    
898            private PortletCategory _readLiferayDisplayXML(String xml)
899                    throws Exception {
900    
901                    return _readLiferayDisplayXML(null, xml);
902            }
903    
904            private PortletCategory _readLiferayDisplayXML(
905                            String servletContextName, String xml)
906                    throws Exception {
907    
908                    PortletCategory portletCategory = new PortletCategory();
909    
910                    if (xml == null) {
911                            xml = ContentUtil.get(
912                                    "com/liferay/portal/deploy/dependencies/liferay-display.xml");
913                    }
914    
915                    Document document = SAXReaderUtil.read(xml, true);
916    
917                    Element rootElement = document.getRootElement();
918    
919                    Set<String> portletIds = new HashSet<String>();
920    
921                    _readLiferayDisplay(
922                            servletContextName, rootElement, portletCategory, portletIds);
923    
924                    // Portlets that do not belong to any categories should default to the
925                    // Undefined category
926    
927                    Set<String> undefinedPortletIds = new HashSet<String>();
928    
929                    for (Portlet portlet : _getPortletsPool().values()) {
930                            String portletId = portlet.getPortletId();
931    
932                            PortletApp portletApp = portlet.getPortletApp();
933    
934                            if ((servletContextName != null) && (portletApp.isWARFile()) &&
935                                    (portletId.endsWith(
936                                            PortletConstants.WAR_SEPARATOR +
937                                                    PortalUtil.getJsSafePortletId(servletContextName)) &&
938                                    (!portletIds.contains(portletId)))) {
939    
940                                    undefinedPortletIds.add(portletId);
941                            }
942                            else if ((servletContextName == null) &&
943                                             (!portletApp.isWARFile()) &&
944                                             (portletId.indexOf(
945                                                    PortletConstants.WAR_SEPARATOR) == -1) &&
946                                             (!portletIds.contains(portletId))) {
947    
948                                    undefinedPortletIds.add(portletId);
949                            }
950                    }
951    
952                    if (!undefinedPortletIds.isEmpty()) {
953                            PortletCategory undefinedCategory = new PortletCategory(
954                                    "category.undefined");
955    
956                            portletCategory.addCategory(undefinedCategory);
957    
958                            undefinedCategory.getPortletIds().addAll(undefinedPortletIds);
959                    }
960    
961                    return portletCategory;
962            }
963    
964            private Set<String> _readLiferayPortletXML(
965                            String xml, Map<String, Portlet> portletsPool)
966                    throws Exception {
967    
968                    return _readLiferayPortletXML(StringPool.BLANK, xml, portletsPool);
969            }
970    
971            private void _readLiferayPortletXML(
972                    String servletContextName, Map<String, Portlet> portletsPool,
973                    Set<String> liferayPortletIds, Map<String, String> roleMappers,
974                    Element portletElement) {
975    
976                    String portletId = portletElement.elementText("portlet-name");
977    
978                    if (Validator.isNotNull(servletContextName)) {
979                            portletId = portletId.concat(PortletConstants.WAR_SEPARATOR).concat(
980                                    servletContextName);
981                    }
982    
983                    portletId = PortalUtil.getJsSafePortletId(portletId);
984    
985                    if (_log.isDebugEnabled()) {
986                            _log.debug("Reading portlet extension " + portletId);
987                    }
988    
989                    liferayPortletIds.add(portletId);
990    
991                    Portlet portletModel = portletsPool.get(portletId);
992    
993                    if (portletModel == null) {
994                            return;
995                    }
996    
997                    portletModel.setIcon(
998                            GetterUtil.getString(
999                                    portletElement.elementText("icon"), portletModel.getIcon()));
1000                    portletModel.setVirtualPath(
1001                            GetterUtil.getString(
1002                                    portletElement.elementText("virtual-path"),
1003                                    portletModel.getVirtualPath()));
1004                    portletModel.setStrutsPath(
1005                            GetterUtil.getString(
1006                                    portletElement.elementText("struts-path"),
1007                                    portletModel.getStrutsPath()));
1008    
1009                    if (Validator.isNotNull(
1010                                    portletElement.elementText("configuration-path"))) {
1011    
1012                            _log.error(
1013                                    "The configuration-path element is no longer supported. Use " +
1014                                            "configuration-action-class instead.");
1015                    }
1016    
1017                    portletModel.setConfigurationActionClass(
1018                            GetterUtil.getString(
1019                                    portletElement.elementText("configuration-action-class"),
1020                                    portletModel.getConfigurationActionClass()));
1021                    portletModel.setIndexerClass(
1022                            GetterUtil.getString(
1023                                    portletElement.elementText("indexer-class"),
1024                                    portletModel.getIndexerClass()));
1025                    portletModel.setOpenSearchClass(
1026                            GetterUtil.getString(
1027                                    portletElement.elementText("open-search-class"),
1028                                    portletModel.getOpenSearchClass()));
1029    
1030                    for (Element schedulerEntryElement :
1031                                    portletElement.elements("scheduler-entry")) {
1032    
1033                            SchedulerEntry schedulerEntry = new SchedulerEntryImpl();
1034    
1035                            schedulerEntry.setDescription(
1036                                    GetterUtil.getString(
1037                                            schedulerEntryElement.elementText(
1038                                                    "scheduler-description")));
1039                            schedulerEntry.setEventListenerClass(
1040                                    GetterUtil.getString(
1041                                            schedulerEntryElement.elementText(
1042                                                    "scheduler-event-listener-class"),
1043                                            schedulerEntry.getEventListenerClass()));
1044    
1045                            Element triggerElement = schedulerEntryElement.element("trigger");
1046    
1047                            Element cronElement = triggerElement.element("cron");
1048                            Element simpleElement = triggerElement.element("simple");
1049    
1050                            if (cronElement != null) {
1051                                    schedulerEntry.setTriggerType(TriggerType.CRON);
1052    
1053                                    Element propertyKeyElement = cronElement.element(
1054                                            "property-key");
1055    
1056                                    if (propertyKeyElement != null) {
1057                                            schedulerEntry.setPropertyKey(
1058                                                    propertyKeyElement.getTextTrim());
1059                                    }
1060                                    else {
1061                                            schedulerEntry.setTriggerValue(
1062                                                    cronElement.elementText("cron-trigger-value"));
1063                                    }
1064                            }
1065                            else if (simpleElement != null) {
1066                                    schedulerEntry.setTriggerType(TriggerType.SIMPLE);
1067    
1068                                    Element propertyKeyElement = simpleElement.element(
1069                                            "property-key");
1070    
1071                                    if (propertyKeyElement != null) {
1072                                            schedulerEntry.setPropertyKey(
1073                                                    propertyKeyElement.getTextTrim());
1074                                    }
1075                                    else {
1076                                            Element simpleTriggerValueElement = simpleElement.element(
1077                                                    "simple-trigger-value");
1078    
1079                                            schedulerEntry.setTriggerValue(
1080                                                    simpleTriggerValueElement.getTextTrim());
1081                                    }
1082    
1083                                    String timeUnit = GetterUtil.getString(
1084                                            simpleElement.elementText("time-unit"),
1085                                            TimeUnit.SECOND.getValue());
1086    
1087                                    schedulerEntry.setTimeUnit(
1088                                            TimeUnit.parse(timeUnit.toLowerCase()));
1089                            }
1090    
1091                            portletModel.addSchedulerEntry(schedulerEntry);
1092                    }
1093    
1094                    portletModel.setPortletURLClass(
1095                            GetterUtil.getString(
1096                                    portletElement.elementText("portlet-url-class"),
1097                                    portletModel.getPortletURLClass()));
1098    
1099                    portletModel.setFriendlyURLMapperClass(
1100                            GetterUtil.getString(
1101                                    portletElement.elementText("friendly-url-mapper-class"),
1102                                    portletModel.getFriendlyURLMapperClass()));
1103    
1104                    if (Validator.isNull(portletModel.getFriendlyURLMapperClass())) {
1105                            _friendlyURLMapperPortlets.remove(portletId);
1106                    }
1107                    else {
1108                            _friendlyURLMapperPortlets.put(portletId, portletModel);
1109                    }
1110    
1111                    portletModel.setFriendlyURLMapping(
1112                            GetterUtil.getString(
1113                                    portletElement.elementText("friendly-url-mapping"),
1114                                    portletModel.getFriendlyURLMapping()));
1115                    portletModel.setFriendlyURLRoutes(
1116                            GetterUtil.getString(
1117                                    portletElement.elementText("friendly-url-routes"),
1118                                    portletModel.getFriendlyURLRoutes()));
1119                    portletModel.setURLEncoderClass(
1120                            GetterUtil.getString(
1121                                    portletElement.elementText("url-encoder-class"),
1122                                    portletModel.getURLEncoderClass()));
1123                    portletModel.setPortletDataHandlerClass(
1124                            GetterUtil.getString(
1125                                    portletElement.elementText("portlet-data-handler-class"),
1126                                    portletModel.getPortletDataHandlerClass()));
1127                    portletModel.setPortletLayoutListenerClass(
1128                            GetterUtil.getString(
1129                                    portletElement.elementText("portlet-layout-listener-class"),
1130                                    portletModel.getPortletLayoutListenerClass()));
1131                    portletModel.setPollerProcessorClass(
1132                            GetterUtil.getString(
1133                                    portletElement.elementText("poller-processor-class"),
1134                                    portletModel.getPollerProcessorClass()));
1135                    portletModel.setPopMessageListenerClass(
1136                            GetterUtil.getString(
1137                                    portletElement.elementText("pop-message-listener-class"),
1138                                    portletModel.getPopMessageListenerClass()));
1139                    portletModel.setSocialActivityInterpreterClass(
1140                            GetterUtil.getString(
1141                                    portletElement.elementText(
1142                                            "social-activity-interpreter-class"),
1143                                            portletModel.getSocialActivityInterpreterClass()));
1144                    portletModel.setSocialRequestInterpreterClass(
1145                            GetterUtil.getString(
1146                                    portletElement.elementText(
1147                                            "social-request-interpreter-class"),
1148                                            portletModel.getSocialRequestInterpreterClass()));
1149                    portletModel.setWebDAVStorageToken(
1150                            GetterUtil.getString(
1151                                    portletElement.elementText("webdav-storage-token"),
1152                                    portletModel.getWebDAVStorageToken()));
1153                    portletModel.setWebDAVStorageClass(
1154                            GetterUtil.getString(
1155                                    portletElement.elementText("webdav-storage-class"),
1156                                    portletModel.getWebDAVStorageClass()));
1157                    portletModel.setXmlRpcMethodClass(
1158                            GetterUtil.getString(
1159                                    portletElement.elementText("xml-rpc-method-class"),
1160                                    portletModel.getXmlRpcMethodClass()));
1161                    portletModel.setControlPanelEntryCategory(
1162                            GetterUtil.getString(
1163                                    portletElement.elementText("control-panel-entry-category"),
1164                                    portletModel.getControlPanelEntryCategory()));
1165                    portletModel.setControlPanelEntryWeight(
1166                            GetterUtil.getDouble(
1167                                    portletElement.elementText("control-panel-entry-weight"),
1168                                    portletModel.getControlPanelEntryWeight()));
1169                    portletModel.setControlPanelEntryClass(
1170                            GetterUtil.getString(
1171                                    portletElement.elementText("control-panel-entry-class"),
1172                                    portletModel.getControlPanelEntryClass()));
1173    
1174                    List<String> assetRendererFactoryClasses =
1175                            portletModel.getAssetRendererFactoryClasses();
1176    
1177                    for (Element assetRendererFactoryClassElement :
1178                                    portletElement.elements("asset-renderer-factory")) {
1179    
1180                            assetRendererFactoryClasses.add(
1181                                    assetRendererFactoryClassElement.getText());
1182                    }
1183    
1184                    List<String> customAttributesDisplayClasses =
1185                            portletModel.getCustomAttributesDisplayClasses();
1186    
1187                    for (Element customAttributesDisplayClassElement :
1188                                    portletElement.elements("custom-attributes-display")) {
1189    
1190                            customAttributesDisplayClasses.add(
1191                                    customAttributesDisplayClassElement.getText());
1192                    }
1193    
1194                    if (customAttributesDisplayClasses.isEmpty()) {
1195                            _customAttributesDisplayPortlets.remove(portletId);
1196                    }
1197                    else {
1198                            _customAttributesDisplayPortlets.put(portletId, portletModel);
1199                    }
1200    
1201                    List<String> workflowHandlerClasses =
1202                            portletModel.getWorkflowHandlerClasses();
1203    
1204                    for (Element workflowHandlerClassElement :
1205                                    portletElement.elements("workflow-handler")) {
1206    
1207                            workflowHandlerClasses.add(workflowHandlerClassElement.getText());
1208                    }
1209    
1210                    portletModel.setPreferencesCompanyWide(
1211                            GetterUtil.getBoolean(
1212                                    portletElement.elementText("preferences-company-wide"),
1213                                    portletModel.isPreferencesCompanyWide()));
1214                    portletModel.setPreferencesUniquePerLayout(
1215                            GetterUtil.getBoolean(
1216                                    portletElement.elementText("preferences-unique-per-layout"),
1217                                    portletModel.isPreferencesUniquePerLayout()));
1218                    portletModel.setPreferencesOwnedByGroup(
1219                            GetterUtil.getBoolean(
1220                                    portletElement.elementText("preferences-owned-by-group"),
1221                                    portletModel.isPreferencesOwnedByGroup()));
1222                    portletModel.setUseDefaultTemplate(
1223                            GetterUtil.getBoolean(
1224                                    portletElement.elementText("use-default-template"),
1225                                    portletModel.isUseDefaultTemplate()));
1226                    portletModel.setShowPortletAccessDenied(
1227                            GetterUtil.getBoolean(
1228                                    portletElement.elementText("show-portlet-access-denied"),
1229                                    portletModel.isShowPortletAccessDenied()));
1230                    portletModel.setShowPortletInactive(
1231                            GetterUtil.getBoolean(
1232                                    portletElement.elementText("show-portlet-inactive"),
1233                                    portletModel.isShowPortletInactive()));
1234                    portletModel.setActionURLRedirect(
1235                            GetterUtil.getBoolean(
1236                                    portletElement.elementText("action-url-redirect"),
1237                                    portletModel.isActionURLRedirect()));
1238                    portletModel.setRestoreCurrentView(
1239                            GetterUtil.getBoolean(
1240                                    portletElement.elementText("restore-current-view"),
1241                                    portletModel.isRestoreCurrentView()));
1242                    portletModel.setMaximizeEdit(
1243                            GetterUtil.getBoolean(
1244                                    portletElement.elementText("maximize-edit"),
1245                                    portletModel.isMaximizeEdit()));
1246                    portletModel.setMaximizeHelp(
1247                            GetterUtil.getBoolean(
1248                                    portletElement.elementText("maximize-help"),
1249                                    portletModel.isMaximizeHelp()));
1250                    portletModel.setPopUpPrint(
1251                            GetterUtil.getBoolean(
1252                                    portletElement.elementText("pop-up-print"),
1253                                    portletModel.isPopUpPrint()));
1254                    portletModel.setLayoutCacheable(
1255                            GetterUtil.getBoolean(
1256                                    portletElement.elementText("layout-cacheable"),
1257                                    portletModel.isLayoutCacheable()));
1258                    portletModel.setInstanceable(
1259                            GetterUtil.getBoolean(
1260                                    portletElement.elementText("instanceable"),
1261                                    portletModel.isInstanceable()));
1262                    portletModel.setRemoteable(
1263                            GetterUtil.getBoolean(
1264                                    portletElement.elementText("remoteable"),
1265                                    portletModel.isRemoteable()));
1266                    portletModel.setScopeable(
1267                            GetterUtil.getBoolean(
1268                                    portletElement.elementText("scopeable"),
1269                                    portletModel.isScopeable()));
1270                    portletModel.setUserPrincipalStrategy(
1271                            GetterUtil.getString(
1272                                    portletElement.elementText("user-principal-strategy"),
1273                                    portletModel.getUserPrincipalStrategy()));
1274                    portletModel.setPrivateRequestAttributes(
1275                            GetterUtil.getBoolean(
1276                                    portletElement.elementText("private-request-attributes"),
1277                                    portletModel.isPrivateRequestAttributes()));
1278                    portletModel.setPrivateSessionAttributes(
1279                            GetterUtil.getBoolean(
1280                                    portletElement.elementText("private-session-attributes"),
1281                                    portletModel.isPrivateSessionAttributes()));
1282                    portletModel.setRenderWeight(
1283                            GetterUtil.getInteger(
1284                                    portletElement.elementText("render-weight"),
1285                                    portletModel.getRenderWeight()));
1286                    portletModel.setAjaxable(
1287                            GetterUtil.getBoolean(
1288                                    portletElement.elementText("ajaxable"),
1289                                    portletModel.isAjaxable()));
1290    
1291                    List<String> headerPortalCssList =
1292                            portletModel.getHeaderPortalCss();
1293    
1294                    for (Element headerPortalCssElement :
1295                                    portletElement.elements("header-portal-css")) {
1296    
1297                            headerPortalCssList.add(headerPortalCssElement.getText());
1298                    }
1299    
1300                    List<String> headerPortletCssList = portletModel.getHeaderPortletCss();
1301    
1302                    for (Element headerPortletCssElement :
1303                                    portletElement.elements("header-portlet-css")) {
1304    
1305                            headerPortletCssList.add(headerPortletCssElement.getText());
1306                    }
1307    
1308                    List<String> headerPortalJavaScriptList =
1309                            portletModel.getHeaderPortalJavaScript();
1310    
1311                    for (Element headerPortalJavaScriptElement :
1312                                    portletElement.elements("header-portal-javascript")) {
1313    
1314                            headerPortalJavaScriptList.add(
1315                                    headerPortalJavaScriptElement.getText());
1316                    }
1317    
1318                    List<String> headerPortletJavaScriptList =
1319                            portletModel.getHeaderPortletJavaScript();
1320    
1321                    for (Element headerPortletJavaScriptElement :
1322                                    portletElement.elements("header-portlet-javascript")) {
1323    
1324                            headerPortletJavaScriptList.add(
1325                                    headerPortletJavaScriptElement.getText());
1326                    }
1327    
1328                    List<String> footerPortalCssList = portletModel.getFooterPortalCss();
1329    
1330                    for (Element footerPortalCssElement :
1331                                    portletElement.elements("footer-portal-css")) {
1332    
1333                            footerPortalCssList.add(footerPortalCssElement.getText());
1334                    }
1335    
1336                    List<String> footerPortletCssList = portletModel.getFooterPortletCss();
1337    
1338                    for (Element footerPortletCssElement :
1339                                    portletElement.elements("footer-portlet-css")) {
1340    
1341                            footerPortletCssList.add(footerPortletCssElement.getText());
1342                    }
1343    
1344                    List<String> footerPortalJavaScriptList =
1345                            portletModel.getFooterPortalJavaScript();
1346    
1347                    for (Element footerPortalJavaScriptElement :
1348                                    portletElement.elements("footer-portal-javascript")) {
1349    
1350                            footerPortalJavaScriptList.add(
1351                                    footerPortalJavaScriptElement.getText());
1352                    }
1353    
1354                    List<String> footerPortletJavaScriptList =
1355                            portletModel.getFooterPortletJavaScript();
1356    
1357                    for (Element footerPortletJavaScriptElement :
1358                                    portletElement.elements("footer-portlet-javascript")) {
1359    
1360                            footerPortletJavaScriptList.add(
1361                                    footerPortletJavaScriptElement.getText());
1362                    }
1363    
1364                    portletModel.setCssClassWrapper(GetterUtil.getString(
1365                            portletElement.elementText("css-class-wrapper"),
1366                            portletModel.getCssClassWrapper()));
1367                    portletModel.setFacebookIntegration(GetterUtil.getString(
1368                            portletElement.elementText("facebook-integration"),
1369                            portletModel.getFacebookIntegration()));
1370                    portletModel.setAddDefaultResource(GetterUtil.getBoolean(
1371                            portletElement.elementText("add-default-resource"),
1372                            portletModel.isAddDefaultResource()));
1373                    portletModel.setSystem(GetterUtil.getBoolean(
1374                            portletElement.elementText("system"),
1375                            portletModel.isSystem()));
1376                    portletModel.setActive(GetterUtil.getBoolean(
1377                            portletElement.elementText("active"),
1378                            portletModel.isActive()));
1379                    portletModel.setInclude(GetterUtil.getBoolean(
1380                            portletElement.elementText("include"),
1381                            portletModel.isInclude()));
1382    
1383                    if (!portletModel.isAjaxable() &&
1384                            (portletModel.getRenderWeight() < 1)) {
1385    
1386                            portletModel.setRenderWeight(1);
1387                    }
1388    
1389                    portletModel.getRoleMappers().putAll(roleMappers);
1390                    portletModel.linkRoles();
1391            }
1392    
1393            private Set<String> _readLiferayPortletXML(
1394                            String servletContextName, String xml,
1395                            Map<String, Portlet> portletsPool)
1396                    throws Exception {
1397    
1398                    Set<String> liferayPortletIds = new HashSet<String>();
1399    
1400                    if (xml == null) {
1401                            return liferayPortletIds;
1402                    }
1403    
1404                    Document document = SAXReaderUtil.read(xml, true);
1405    
1406                    Element rootElement = document.getRootElement();
1407    
1408                    PortletApp portletApp = _getPortletApp(servletContextName);
1409    
1410                    Map<String, String> roleMappers = new HashMap<String, String>();
1411    
1412                    for (Element roleMapperElement : rootElement.elements("role-mapper")) {
1413                            String roleName = roleMapperElement.elementText("role-name");
1414                            String roleLink = roleMapperElement.elementText("role-link");
1415    
1416                            roleMappers.put(roleName, roleLink);
1417                    }
1418    
1419                    Map<String, String> customUserAttributes =
1420                            portletApp.getCustomUserAttributes();
1421    
1422                    for (Element customUserAttributeElement :
1423                                    rootElement.elements("custom-user-attribute")) {
1424    
1425                            String customClass = customUserAttributeElement.elementText(
1426                                    "custom-class");
1427    
1428                            for (Element nameElement :
1429                                            customUserAttributeElement.elements("name")) {
1430    
1431                                    String name = nameElement.getText();
1432    
1433                                    customUserAttributes.put(name, customClass);
1434                            }
1435                    }
1436    
1437                    for (Element portletElement : rootElement.elements("portlet")) {
1438                            _readLiferayPortletXML(
1439                                    servletContextName, portletsPool, liferayPortletIds,
1440                                    roleMappers, portletElement);
1441                    }
1442    
1443                    return liferayPortletIds;
1444            }
1445    
1446            private Set<String> _readPortletXML(
1447                            ServletContext servletContext, String xml,
1448                            Map<String, Portlet> portletsPool, Set<String> servletURLPatterns,
1449                            PluginPackage pluginPackage)
1450                    throws Exception {
1451    
1452                    return _readPortletXML(
1453                            StringPool.BLANK, servletContext, xml, portletsPool,
1454                            servletURLPatterns, pluginPackage);
1455            }
1456    
1457            private void _readPortletXML(
1458                    String servletContextName, Map<String, Portlet> portletsPool,
1459                    PluginPackage pluginPackage, PortletApp portletApp,
1460                    Set<String> portletIds, long timestamp, Element portletElement) {
1461    
1462                    String portletName = portletElement.elementText("portlet-name");
1463    
1464                    String portletId = portletName;
1465    
1466                    if (Validator.isNotNull(servletContextName)) {
1467                            portletId = portletId.concat(PortletConstants.WAR_SEPARATOR).concat(
1468                                    servletContextName);
1469                    }
1470    
1471                    portletId = PortalUtil.getJsSafePortletId(portletId);
1472    
1473                    if (_log.isDebugEnabled()) {
1474                            _log.debug("Reading portlet " + portletId);
1475                    }
1476    
1477                    portletIds.add(portletId);
1478    
1479                    Portlet portletModel = portletsPool.get(portletId);
1480    
1481                    if (portletModel == null) {
1482                            portletModel = new PortletImpl(CompanyConstants.SYSTEM, portletId);
1483    
1484                            portletsPool.put(portletId, portletModel);
1485                    }
1486    
1487                    portletModel.setTimestamp(timestamp);
1488    
1489                    portletModel.setPluginPackage(pluginPackage);
1490                    portletModel.setPortletApp(portletApp);
1491    
1492                    portletModel.setPortletName(portletName);
1493                    portletModel.setDisplayName(
1494                            GetterUtil.getString(
1495                                    portletElement.elementText("display-name"),
1496                                    portletModel.getDisplayName()));
1497                    portletModel.setPortletClass(
1498                            GetterUtil.getString(portletElement.elementText("portlet-class")));
1499    
1500                    Map<String, String> initParams = portletModel.getInitParams();
1501    
1502                    for (Element initParamElement : portletElement.elements("init-param")) {
1503                            initParams.put(
1504                                    initParamElement.elementText("name"),
1505                                    initParamElement.elementText("value"));
1506                    }
1507    
1508                    Element expirationCacheElement = portletElement.element(
1509                            "expiration-cache");
1510    
1511                    if (expirationCacheElement != null) {
1512                            portletModel.setExpCache(
1513                                    GetterUtil.getInteger(expirationCacheElement.getText()));
1514                    }
1515    
1516                    for (Element supportsElement : portletElement.elements("supports")) {
1517                            Map<String, Set<String>> portletModes =
1518                                    portletModel.getPortletModes();
1519    
1520                            String mimeType = supportsElement.elementText("mime-type");
1521    
1522                            Set<String> mimeTypePortletModes = portletModes.get(mimeType);
1523    
1524                            if (mimeTypePortletModes == null) {
1525                                    mimeTypePortletModes = new HashSet<String>();
1526    
1527                                    portletModes.put(mimeType, mimeTypePortletModes);
1528                            }
1529    
1530                            mimeTypePortletModes.add(PortletMode.VIEW.toString().toLowerCase());
1531    
1532                            for (Element portletModeElement :
1533                                            supportsElement.elements("portlet-mode")) {
1534    
1535                                    mimeTypePortletModes.add(
1536                                            portletModeElement.getTextTrim().toLowerCase());
1537                            }
1538    
1539                            Map<String, Set<String>> windowStates =
1540                                    portletModel.getWindowStates();
1541    
1542                            Set<String> mimeTypeWindowStates = windowStates.get(mimeType);
1543    
1544                            if (mimeTypeWindowStates == null) {
1545                                    mimeTypeWindowStates = new HashSet<String>();
1546    
1547                                    windowStates.put(mimeType, mimeTypeWindowStates);
1548                            }
1549    
1550                            mimeTypeWindowStates.add(
1551                                    WindowState.NORMAL.toString().toLowerCase());
1552    
1553                            List<Element> windowStateElements = supportsElement.elements(
1554                                    "window-state");
1555    
1556                            if (windowStateElements.isEmpty()) {
1557                                    mimeTypeWindowStates.add(
1558                                            WindowState.MAXIMIZED.toString().toLowerCase());
1559                                    mimeTypeWindowStates.add(
1560                                            WindowState.MINIMIZED.toString().toLowerCase());
1561                                    mimeTypeWindowStates.add(
1562                                            LiferayWindowState.EXCLUSIVE.toString().toLowerCase());
1563                                    mimeTypeWindowStates.add(
1564                                            LiferayWindowState.POP_UP.toString().toLowerCase());
1565                            }
1566    
1567                            for (Element windowStateElement : windowStateElements) {
1568                                    mimeTypeWindowStates.add(
1569                                            windowStateElement.getTextTrim().toLowerCase());
1570                            }
1571                    }
1572    
1573                    Set<String> supportedLocales = portletModel.getSupportedLocales();
1574    
1575                    //supportedLocales.add(
1576                    //        LocaleUtil.toLanguageId(LocaleUtil.getDefault()));
1577    
1578                    for (Element supportedLocaleElement : portletElement.elements(
1579                                    "supported-locale")) {
1580    
1581                            String supportedLocale = supportedLocaleElement.getText();
1582    
1583                            supportedLocales.add(supportedLocale);
1584                    }
1585    
1586                    portletModel.setResourceBundle(
1587                            portletElement.elementText("resource-bundle"));
1588    
1589                    Element portletInfoElement = portletElement.element("portlet-info");
1590    
1591                    String portletInfoTitle = null;
1592                    String portletInfoShortTitle = null;
1593                    String portletInfoKeyWords = null;
1594                    String portletInfoDescription = null;
1595    
1596                    if (portletInfoElement != null) {
1597                            portletInfoTitle = portletInfoElement.elementText("title");
1598                            portletInfoShortTitle = portletInfoElement.elementText(
1599                                    "short-title");
1600                            portletInfoKeyWords = portletInfoElement.elementText("keywords");
1601                    }
1602    
1603                    PortletInfo portletInfo = new PortletInfo(
1604                            portletInfoTitle, portletInfoShortTitle, portletInfoKeyWords,
1605                            portletInfoDescription);
1606    
1607                    portletModel.setPortletInfo(portletInfo);
1608    
1609                    Element portletPreferencesElement = portletElement.element(
1610                            "portlet-preferences");
1611    
1612                    String defaultPreferences = null;
1613                    String preferencesValidator = null;
1614    
1615                    if (portletPreferencesElement != null) {
1616                            Element preferencesValidatorElement =
1617                                    portletPreferencesElement.element("preferences-validator");
1618    
1619                            if (preferencesValidatorElement != null) {
1620                                    preferencesValidator = preferencesValidatorElement.getText();
1621    
1622                                    portletPreferencesElement.remove(preferencesValidatorElement);
1623                            }
1624    
1625                            defaultPreferences = portletPreferencesElement.asXML();
1626                    }
1627    
1628                    portletModel.setDefaultPreferences(defaultPreferences);
1629                    portletModel.setPreferencesValidator(preferencesValidator);
1630    
1631                    if (!portletApp.isWARFile() &&
1632                            Validator.isNotNull(preferencesValidator) &&
1633                            PropsValues.PREFERENCE_VALIDATE_ON_STARTUP) {
1634    
1635                            try {
1636                                    PreferencesValidator preferencesValidatorObj =
1637                                            PortalUtil.getPreferencesValidator(portletModel);
1638    
1639                                    preferencesValidatorObj.validate(
1640                                            PortletPreferencesSerializer.fromDefaultXML(
1641                                                    defaultPreferences));
1642                            }
1643                            catch (Exception e) {
1644                                    if (_log.isWarnEnabled()) {
1645                                            _log.warn(
1646                                                    "Portlet with the name " + portletId +
1647                                                            " does not have valid default preferences");
1648                                    }
1649                            }
1650                    }
1651    
1652                    Set<String> unlikedRoles = portletModel.getUnlinkedRoles();
1653    
1654                    for (Element roleElement :
1655                                    portletElement.elements("security-role-ref")) {
1656    
1657                            unlikedRoles.add(roleElement.elementText("role-name"));
1658                    }
1659    
1660                    for (Element supportedProcessingEventElement :
1661                                    portletElement.elements("supported-processing-event")) {
1662    
1663                            Element qNameElement = supportedProcessingEventElement.element(
1664                                    "qname");
1665                            Element nameElement = supportedProcessingEventElement.element(
1666                                    "name");
1667    
1668                            QName qName = PortletQNameUtil.getQName(
1669                                    qNameElement, nameElement, portletApp.getDefaultNamespace());
1670    
1671                            portletModel.addProcessingEvent(qName);
1672                    }
1673    
1674                    for (Element supportedPublishingEventElement :
1675                                    portletElement.elements("supported-publishing-event")) {
1676    
1677                            Element qNameElement = supportedPublishingEventElement.element(
1678                                    "qname");
1679                            Element nameElement = supportedPublishingEventElement.element(
1680                                    "name");
1681    
1682                            QName qName = PortletQNameUtil.getQName(
1683                                    qNameElement, nameElement, portletApp.getDefaultNamespace());
1684    
1685                            portletModel.addPublishingEvent(qName);
1686                    }
1687    
1688                    for (Element supportedPublicRenderParameter :
1689                                    portletElement.elements("supported-public-render-parameter")) {
1690    
1691                            String identifier = supportedPublicRenderParameter.getTextTrim();
1692    
1693                            PublicRenderParameter publicRenderParameter =
1694                                    portletApp.getPublicRenderParameter(identifier);
1695    
1696                            if (publicRenderParameter == null) {
1697                                    _log.error(
1698                                            "Supported public render parameter references " +
1699                                                    "unnknown identifier " + identifier);
1700    
1701                                    continue;
1702                            }
1703    
1704                            portletModel.addPublicRenderParameter(publicRenderParameter);
1705                    }
1706            }
1707    
1708            private Set<String> _readPortletXML(
1709                            String servletContextName, ServletContext servletContext,
1710                            String xml, Map<String, Portlet> portletsPool,
1711                            Set<String> servletURLPatterns, PluginPackage pluginPackage)
1712                    throws Exception {
1713    
1714                    Set<String> portletIds = new HashSet<String>();
1715    
1716                    if (xml == null) {
1717                            return portletIds;
1718                    }
1719    
1720                    Document document = SAXReaderUtil.read(
1721                            xml, PropsValues.PORTLET_XML_VALIDATE);
1722    
1723                    Element rootElement = document.getRootElement();
1724    
1725                    PortletApp portletApp = _getPortletApp(servletContextName);
1726    
1727                    portletApp.addServletURLPatterns(servletURLPatterns);
1728    
1729                    Set<String> userAttributes = portletApp.getUserAttributes();
1730    
1731                    for (Element userAttributeElement :
1732                                    rootElement.elements("user-attribute")) {
1733    
1734                            String name = userAttributeElement.elementText("name");
1735    
1736                            userAttributes.add(name);
1737                    }
1738    
1739                    String defaultNamespace = rootElement.elementText("default-namespace");
1740    
1741                    if (Validator.isNotNull(defaultNamespace)) {
1742                            portletApp.setDefaultNamespace(defaultNamespace);
1743                    }
1744    
1745                    for (Element eventDefinitionElement :
1746                                    rootElement.elements("event-definition")) {
1747    
1748                            Element qNameElement = eventDefinitionElement.element("qname");
1749                            Element nameElement = eventDefinitionElement.element("name");
1750                            String valueType = eventDefinitionElement.elementText("value-type");
1751    
1752                            QName qName = PortletQNameUtil.getQName(
1753                                    qNameElement, nameElement, portletApp.getDefaultNamespace());
1754    
1755                            EventDefinition eventDefinition = new EventDefinitionImpl(
1756                                    qName, valueType, portletApp);
1757    
1758                            portletApp.addEventDefinition(eventDefinition);
1759                    }
1760    
1761                    for (Element publicRenderParameterElement :
1762                                    rootElement.elements("public-render-parameter")) {
1763    
1764                            String identifier = publicRenderParameterElement.elementText(
1765                                    "identifier");
1766                            Element qNameElement = publicRenderParameterElement.element(
1767                                    "qname");
1768                            Element nameElement = publicRenderParameterElement.element("name");
1769    
1770                            QName qName = PortletQNameUtil.getQName(
1771                                    qNameElement, nameElement, portletApp.getDefaultNamespace());
1772    
1773                            PublicRenderParameter publicRenderParameter =
1774                                    new PublicRenderParameterImpl(identifier, qName, portletApp);
1775    
1776                            portletApp.addPublicRenderParameter(publicRenderParameter);
1777                    }
1778    
1779                    for (Element containerRuntimeOptionElement :
1780                                    rootElement.elements("container-runtime-option")) {
1781    
1782                            String name = GetterUtil.getString(
1783                                    containerRuntimeOptionElement.elementText("name"));
1784    
1785                            List<String> values = new ArrayList<String>();
1786    
1787                            for (Element valueElement :
1788                                            containerRuntimeOptionElement.elements("value")) {
1789    
1790                                    values.add(valueElement.getTextTrim());
1791                            }
1792    
1793                            Map<String, String[]> containerRuntimeOptions =
1794                                    portletApp.getContainerRuntimeOptions();
1795    
1796                            containerRuntimeOptions.put(
1797                                    name, values.toArray(new String[values.size()]));
1798    
1799                            if (name.equals(
1800                                            LiferayPortletConfig.RUNTIME_OPTION_PORTAL_CONTEXT) &&
1801                                    !values.isEmpty() && GetterUtil.getBoolean(values.get(0))) {
1802    
1803                                    portletApp.setWARFile(false);
1804                            }
1805                    }
1806    
1807                    long timestamp = ServletContextUtil.getLastModified(servletContext);
1808    
1809                    for (Element portletElement : rootElement.elements("portlet")) {
1810                            _readPortletXML(
1811                                    servletContextName, portletsPool, pluginPackage, portletApp,
1812                                    portletIds, timestamp, portletElement);
1813                    }
1814    
1815                    for (Element filterElement : rootElement.elements("filter")) {
1816                            String filterName = filterElement.elementText("filter-name");
1817                            String filterClass = filterElement.elementText("filter-class");
1818    
1819                            Set<String> lifecycles = new LinkedHashSet<String>();
1820    
1821                            for (Element lifecycleElement :
1822                                            filterElement.elements("lifecycle")) {
1823    
1824                                    lifecycles.add(lifecycleElement.getText());
1825                            }
1826    
1827                            Map<String, String> initParams = new HashMap<String, String>();
1828    
1829                            for (Element initParamElement :
1830                                            filterElement.elements("init-param")) {
1831    
1832                                    initParams.put(
1833                                            initParamElement.elementText("name"),
1834                                            initParamElement.elementText("value"));
1835                            }
1836    
1837                            PortletFilter portletFilter = new PortletFilterImpl(
1838                                    filterName, filterClass, lifecycles, initParams, portletApp);
1839    
1840                            portletApp.addPortletFilter(portletFilter);
1841                    }
1842    
1843                    for (Element filterMappingElement :
1844                                    rootElement.elements("filter-mapping")) {
1845    
1846                            String filterName = filterMappingElement.elementText("filter-name");
1847    
1848                            for (Element portletNameElement :
1849                                            filterMappingElement.elements("portlet-name")) {
1850    
1851                                    String portletName = portletNameElement.getTextTrim();
1852    
1853                                    PortletFilter portletFilter = portletApp.getPortletFilter(
1854                                            filterName);
1855    
1856                                    if (portletFilter == null) {
1857                                            _log.error(
1858                                                    "Filter mapping references unnknown filter name " +
1859                                                            filterName);
1860    
1861                                            continue;
1862                                    }
1863    
1864                                    List<Portlet> portletModels = _getPortletsByPortletName(
1865                                            portletName, servletContextName, portletsPool);
1866    
1867                                    if (portletModels.size() == 0) {
1868                                            _log.error(
1869                                                    "Filter mapping with filter name " + filterName +
1870                                                            " references unnknown portlet name " + portletName);
1871                                    }
1872    
1873                                    for (Portlet portletModel : portletModels) {
1874                                            portletModel.getPortletFilters().put(
1875                                                    filterName, portletFilter);
1876                                    }
1877                            }
1878                    }
1879    
1880                    for (Element listenerElement : rootElement.elements("listener")) {
1881                            String listenerClass = listenerElement.elementText(
1882                                    "listener-class");
1883    
1884                            PortletURLListener portletURLListener = new PortletURLListenerImpl(
1885                                    listenerClass, portletApp);
1886    
1887                            portletApp.addPortletURLListener(portletURLListener);
1888                    }
1889    
1890                    return portletIds;
1891            }
1892    
1893            private Set<String> _readWebXML(String xml) throws Exception {
1894                    Set<String> servletURLPatterns = new LinkedHashSet<String>();
1895    
1896                    if (xml == null) {
1897                            return servletURLPatterns;
1898                    }
1899    
1900                    Document document = SAXReaderUtil.read(xml);
1901    
1902                    Element rootElement = document.getRootElement();
1903    
1904                    for (Element servletMappingElement :
1905                                    rootElement.elements("servlet-mapping")) {
1906    
1907                            String urlPattern = servletMappingElement.elementText(
1908                                    "url-pattern");
1909    
1910                            servletURLPatterns.add(urlPattern);
1911                    }
1912    
1913                    return servletURLPatterns;
1914            }
1915    
1916            private void _setSpriteImages(
1917                            ServletContext servletContext, PortletApp portletApp,
1918                            String resourcePath)
1919                    throws Exception {
1920    
1921                    Set<String> resourcePaths = servletContext.getResourcePaths(
1922                            resourcePath);
1923    
1924                    if (resourcePaths == null) {
1925                            return;
1926                    }
1927    
1928                    List<File> images = new ArrayList<File>(resourcePaths.size());
1929    
1930                    for (String curResourcePath : resourcePaths) {
1931                            if (curResourcePath.endsWith(StringPool.SLASH)) {
1932                                    _setSpriteImages(servletContext, portletApp, curResourcePath);
1933                            }
1934                            else if (curResourcePath.endsWith(".png")) {
1935                                    String realPath = ServletContextUtil.getRealPath(
1936                                            servletContext, curResourcePath);
1937    
1938                                    if (realPath != null) {
1939                                            images.add(new File(realPath));
1940                                    }
1941                                    else {
1942                                            if (ServerDetector.isTomcat()) {
1943                                                    if (_log.isInfoEnabled()) {
1944                                                            _log.info(ServletContextUtil.LOG_INFO_SPRITES);
1945                                                    }
1946                                            }
1947                                            else {
1948                                                    _log.error(
1949                                                            "Real path for " + curResourcePath + " is null");
1950                                            }
1951                                    }
1952                            }
1953                    }
1954    
1955                    String spriteFileName = ".sprite.png";
1956                    String spritePropertiesFileName = ".sprite.properties";
1957                    String spritePropertiesRootPath = ServletContextUtil.getRealPath(
1958                            servletContext, StringPool.SLASH);
1959    
1960                    Properties spriteProperties = SpriteProcessorUtil.generate(
1961                            images, spriteFileName, spritePropertiesFileName,
1962                            spritePropertiesRootPath, 16, 16, 10240);
1963    
1964                    if (spriteProperties == null) {
1965                            return;
1966                    }
1967    
1968                    spriteFileName =
1969                            resourcePath.substring(0, resourcePath.length()) + spriteFileName;
1970    
1971                    portletApp.setSpriteImages(spriteFileName, spriteProperties);
1972            }
1973    
1974            private void _updateCompanyPortletsPool(long companyId) {
1975                    String key = _encodeKey(companyId);
1976    
1977                    Map<String, Portlet> portletsPool =
1978                            (Map<String, Portlet>)_companyPortletsPool.get(key);
1979    
1980                    _companyPortletsPool.put(key, portletsPool);
1981            }
1982    
1983            private static Log _log = LogFactoryUtil.getLog(
1984                    PortletLocalServiceImpl.class);
1985    
1986            private static PortalCache _companyPortletsPool =
1987                    MultiVMPoolUtil.getCache(Portlet.class.getName());
1988            private static Map<String, Portlet> _customAttributesDisplayPortlets =
1989                    new ConcurrentHashMap<String, Portlet>();
1990            private static Map<String, Portlet> _friendlyURLMapperPortlets =
1991                    new ConcurrentHashMap<String, Portlet>();
1992            private static String _keyPrefix = Portlet.class.getName().concat(
1993                    StringPool.POUND);
1994            private static Map<String, PortletApp> _portletAppsPool =
1995                    new ConcurrentHashMap<String, PortletApp>();
1996            private static Map<String, String> _portletIdsByStrutsPath =
1997                    new ConcurrentHashMap<String, String>();
1998            private static Map<String, Portlet> _portletsPool =
1999                    new ConcurrentHashMap<String, Portlet>();
2000    
2001    }