001    /**
002     * Copyright (c) 2000-present 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.admin.kernel.util.PortalMyAccountApplicationType;
018    import com.liferay.portal.exception.PortletIdException;
019    import com.liferay.portal.kernel.application.type.ApplicationType;
020    import com.liferay.portal.kernel.cluster.Clusterable;
021    import com.liferay.portal.kernel.configuration.Configuration;
022    import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
023    import com.liferay.portal.kernel.exception.PortalException;
024    import com.liferay.portal.kernel.exception.SystemException;
025    import com.liferay.portal.kernel.image.SpriteProcessor;
026    import com.liferay.portal.kernel.image.SpriteProcessorUtil;
027    import com.liferay.portal.kernel.log.Log;
028    import com.liferay.portal.kernel.log.LogFactoryUtil;
029    import com.liferay.portal.kernel.plugin.PluginPackage;
030    import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
031    import com.liferay.portal.kernel.portlet.LiferayPortletConfig;
032    import com.liferay.portal.kernel.portlet.LiferayWindowState;
033    import com.liferay.portal.kernel.portlet.PortletLayoutListener;
034    import com.liferay.portal.kernel.portlet.PortletProvider;
035    import com.liferay.portal.kernel.portlet.PortletProviderUtil;
036    import com.liferay.portal.kernel.scheduler.SchedulerEntryImpl;
037    import com.liferay.portal.kernel.scheduler.TimeUnit;
038    import com.liferay.portal.kernel.scheduler.TriggerFactoryUtil;
039    import com.liferay.portal.kernel.security.permission.ActionKeys;
040    import com.liferay.portal.kernel.security.permission.ResourceActionsUtil;
041    import com.liferay.portal.kernel.servlet.ServletContextUtil;
042    import com.liferay.portal.kernel.spring.aop.Skip;
043    import com.liferay.portal.kernel.transaction.Transactional;
044    import com.liferay.portal.kernel.util.CharPool;
045    import com.liferay.portal.kernel.util.ClassLoaderPool;
046    import com.liferay.portal.kernel.util.ContentTypes;
047    import com.liferay.portal.kernel.util.GetterUtil;
048    import com.liferay.portal.kernel.util.ListUtil;
049    import com.liferay.portal.kernel.util.StringPool;
050    import com.liferay.portal.kernel.util.StringUtil;
051    import com.liferay.portal.kernel.util.Validator;
052    import com.liferay.portal.kernel.util.WebKeys;
053    import com.liferay.portal.kernel.xml.Document;
054    import com.liferay.portal.kernel.xml.Element;
055    import com.liferay.portal.kernel.xml.QName;
056    import com.liferay.portal.kernel.xml.UnsecureSAXReaderUtil;
057    import com.liferay.portal.model.CompanyConstants;
058    import com.liferay.portal.model.EventDefinition;
059    import com.liferay.portal.model.Portlet;
060    import com.liferay.portal.model.PortletApp;
061    import com.liferay.portal.model.PortletCategory;
062    import com.liferay.portal.model.PortletConstants;
063    import com.liferay.portal.model.PortletFilter;
064    import com.liferay.portal.model.PortletInfo;
065    import com.liferay.portal.model.PortletInstance;
066    import com.liferay.portal.model.PortletPreferences;
067    import com.liferay.portal.model.PortletURLListener;
068    import com.liferay.portal.model.PublicRenderParameter;
069    import com.liferay.portal.model.ResourceConstants;
070    import com.liferay.portal.model.Role;
071    import com.liferay.portal.model.impl.EventDefinitionImpl;
072    import com.liferay.portal.model.impl.PortletAppImpl;
073    import com.liferay.portal.model.impl.PortletFilterImpl;
074    import com.liferay.portal.model.impl.PortletImpl;
075    import com.liferay.portal.model.impl.PortletURLListenerImpl;
076    import com.liferay.portal.model.impl.PublicRenderParameterImpl;
077    import com.liferay.portal.service.base.PortletLocalServiceBaseImpl;
078    import com.liferay.portal.service.permission.PortletPermissionUtil;
079    import com.liferay.portal.servlet.ComboServlet;
080    import com.liferay.portal.util.PortalUtil;
081    import com.liferay.portal.util.PortletKeys;
082    import com.liferay.portal.util.PropsValues;
083    import com.liferay.portal.util.WebAppPool;
084    import com.liferay.portlet.PortletBagFactory;
085    import com.liferay.portlet.PortletConfigFactoryUtil;
086    import com.liferay.portlet.PortletContextFactory;
087    import com.liferay.portlet.PortletInstanceFactoryUtil;
088    import com.liferay.portlet.PortletPreferencesFactoryUtil;
089    import com.liferay.portlet.PortletQNameUtil;
090    import com.liferay.portlet.UndeployedPortlet;
091    import com.liferay.portlet.expando.model.CustomAttributesDisplay;
092    import com.liferay.util.ContentUtil;
093    
094    import java.net.URL;
095    
096    import java.util.ArrayList;
097    import java.util.Collections;
098    import java.util.HashMap;
099    import java.util.HashSet;
100    import java.util.Iterator;
101    import java.util.LinkedHashSet;
102    import java.util.List;
103    import java.util.Map;
104    import java.util.Properties;
105    import java.util.Set;
106    import java.util.concurrent.ConcurrentHashMap;
107    
108    import javax.portlet.PortletMode;
109    import javax.portlet.PreferencesValidator;
110    import javax.portlet.WindowState;
111    
112    import javax.servlet.ServletContext;
113    
114    /**
115     * @author Brian Wing Shun Chan
116     * @author Raymond Aug??
117     * @author Eduardo Lundgren
118     * @author Wesley Gong
119     * @author Shuyang Zhou
120     */
121    public class PortletLocalServiceImpl extends PortletLocalServiceBaseImpl {
122    
123            @Override
124            @Skip
125            public void addPortletCategory(long companyId, String categoryName) {
126                    PortletCategory portletCategory = (PortletCategory)WebAppPool.get(
127                            companyId, WebKeys.PORTLET_CATEGORY);
128    
129                    if (portletCategory == null) {
130                            _log.error(
131                                    "Unable to add portlet category for company " + companyId +
132                                            " because it does not exist");
133    
134                            return;
135                    }
136    
137                    PortletCategory newPortletCategory = new PortletCategory(categoryName);
138    
139                    if (newPortletCategory.getParentCategory() == null) {
140                            PortletCategory rootPortletCategory = new PortletCategory();
141    
142                            rootPortletCategory.addCategory(newPortletCategory);
143                    }
144    
145                    portletCategory.merge(newPortletCategory.getRootCategory());
146            }
147    
148            @Override
149            public void checkPortlet(Portlet portlet) throws PortalException {
150                    long companyId = portlet.getCompanyId();
151                    String name = portlet.getRootPortletId();
152    
153                    int resourcePermissionsCount =
154                            resourcePermissionLocalService.getResourcePermissionsCount(
155                                    companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, name);
156    
157                    if (resourcePermissionsCount == 0) {
158                            resourceLocalService.addResources(
159                                    companyId, 0, 0, name, name, true, false, false);
160                    }
161    
162                    if (portlet.isSystem()) {
163                            return;
164                    }
165    
166                    String[] roleNames = portlet.getRolesArray();
167    
168                    if (roleNames.length == 0) {
169                            return;
170                    }
171    
172                    int scope = ResourceConstants.SCOPE_COMPANY;
173                    String primKey = String.valueOf(companyId);
174                    String actionId = ActionKeys.ADD_TO_PAGE;
175    
176                    List<String> actionIds = ResourceActionsUtil.getPortletResourceActions(
177                            name);
178    
179                    if (actionIds.contains(actionId)) {
180                            for (String roleName : roleNames) {
181                                    Role role = roleLocalService.getRole(companyId, roleName);
182    
183                                    resourcePermissionLocalService.addResourcePermission(
184                                            companyId, name, scope, primKey, role.getRoleId(),
185                                            actionId);
186                            }
187                    }
188    
189                    updatePortlet(
190                            companyId, portlet.getPortletId(), StringPool.BLANK,
191                            portlet.isActive());
192            }
193    
194            @Override
195            public void checkPortlets(long companyId) throws PortalException {
196                    List<Portlet> portlets = getPortlets(companyId);
197    
198                    for (Portlet portlet : portlets) {
199                            checkPortlet(portlet);
200                    }
201            }
202    
203            @Override
204            @Skip
205            public void clearCache() {
206    
207                    // Refresh the combo servlet cache
208    
209                    ComboServlet.clearCache();
210    
211                    // Refresh security path to portlet id mapping for all portlets
212    
213                    _portletIdsByStrutsPath.clear();
214    
215                    // Refresh company portlets
216    
217                    portletLocalService.clearPortletsMap();
218            }
219    
220            /**
221             * @deprecated As of 7.0.0, replaced by {@link #clearPortletsMap)}
222             */
223            @Clusterable
224            @Deprecated
225            @Override
226            @Transactional(enabled = false)
227            public void clearCompanyPortletsPool() {
228                    _portletsMaps.clear();
229            }
230    
231            @Clusterable
232            @Override
233            @Transactional(enabled = false)
234            public void clearPortletsMap() {
235                    _portletsMaps.clear();
236            }
237    
238            @Override
239            @Skip
240            public Portlet clonePortlet(String portletId) {
241                    Portlet portlet = getPortletById(portletId);
242    
243                    return (Portlet)portlet.clone();
244            }
245    
246            @Override
247            public void deletePortlet(long companyId, String portletId, long plid)
248                    throws PortalException {
249    
250                    String rootPortletId = PortletConstants.getRootPortletId(portletId);
251    
252                    resourceLocalService.deleteResource(
253                            companyId, rootPortletId, ResourceConstants.SCOPE_INDIVIDUAL,
254                            PortletPermissionUtil.getPrimaryKey(plid, portletId));
255    
256                    int ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;
257    
258                    if (PortletConstants.hasUserId(portletId)) {
259                            ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
260                    }
261    
262                    List<PortletPreferences> portletPreferencesList =
263                            portletPreferencesLocalService.getPortletPreferences(
264                                    ownerType, plid, portletId);
265    
266                    Portlet portlet = getPortletById(companyId, portletId);
267    
268                    PortletLayoutListener portletLayoutListener = null;
269    
270                    if (portlet != null) {
271                            portletLayoutListener = portlet.getPortletLayoutListenerInstance();
272    
273                            PortletInstanceFactoryUtil.delete(portlet);
274                    }
275    
276                    for (PortletPreferences portletPreferences : portletPreferencesList) {
277                            if (portletLayoutListener != null) {
278                                    portletLayoutListener.onRemoveFromLayout(
279                                            portletPreferences.getPortletId(), plid);
280                            }
281    
282                            portletPreferencesLocalService.deletePortletPreferences(
283                                    portletPreferences.getPortletPreferencesId());
284                    }
285            }
286    
287            @Override
288            public void deletePortlets(long companyId, String[] portletIds, long plid)
289                    throws PortalException {
290    
291                    for (String portletId : portletIds) {
292                            deletePortlet(companyId, portletId, plid);
293                    }
294            }
295    
296            @Override
297            public Portlet deployRemotePortlet(Portlet portlet, String categoryName)
298                    throws PortalException {
299    
300                    return deployRemotePortlet(portlet, new String[] {categoryName});
301            }
302    
303            @Override
304            public Portlet deployRemotePortlet(Portlet portlet, String[] categoryNames)
305                    throws PortalException {
306    
307                    return deployRemotePortlet(portlet, categoryNames, true);
308            }
309    
310            @Override
311            public Portlet deployRemotePortlet(
312                            Portlet portlet, String[] categoryNames, boolean eagerDestroy)
313                    throws PortalException {
314    
315                    _portletsMap.put(portlet.getPortletId(), portlet);
316    
317                    if (eagerDestroy) {
318                            PortletInstanceFactoryUtil.clear(portlet, false);
319    
320                            PortletConfigFactoryUtil.destroy(portlet);
321                    }
322    
323                    clearCache();
324    
325                    List<String> portletActions =
326                            ResourceActionsUtil.getPortletResourceActions(
327                                    portlet.getPortletId());
328    
329                    resourceActionLocalService.checkResourceActions(
330                            portlet.getPortletId(), portletActions);
331    
332                    PortletCategory portletCategory = (PortletCategory)WebAppPool.get(
333                            portlet.getCompanyId(), WebKeys.PORTLET_CATEGORY);
334    
335                    if (portletCategory == null) {
336                            _log.error(
337                                    "Unable to register remote portlet for company " +
338                                            portlet.getCompanyId() + " because it does not exist");
339    
340                            return portlet;
341                    }
342    
343                    portletCategory.separate(portlet.getPortletId());
344    
345                    for (String categoryName : categoryNames) {
346                            PortletCategory newPortletCategory = new PortletCategory(
347                                    categoryName);
348    
349                            if (newPortletCategory.getParentCategory() == null) {
350                                    PortletCategory rootPortletCategory = new PortletCategory();
351    
352                                    rootPortletCategory.addCategory(newPortletCategory);
353                            }
354    
355                            Set<String> portletIds = newPortletCategory.getPortletIds();
356    
357                            portletIds.add(portlet.getPortletId());
358    
359                            portletCategory.merge(newPortletCategory.getRootCategory());
360                    }
361    
362                    checkPortlet(portlet);
363    
364                    return portlet;
365            }
366    
367            @Override
368            @Skip
369            public void destroyPortlet(Portlet portlet) {
370                    _portletsMap.remove(portlet.getRootPortletId());
371    
372                    PortletApp portletApp = portlet.getPortletApp();
373    
374                    if (portletApp != null) {
375                            _portletApps.remove(portletApp.getServletContextName());
376                    }
377    
378                    clearCache();
379            }
380    
381            @Override
382            @Skip
383            public void destroyRemotePortlet(Portlet portlet) {
384                    destroyPortlet(portlet);
385            }
386    
387            @Override
388            @Skip
389            public List<CustomAttributesDisplay> getCustomAttributesDisplays() {
390                    List<CustomAttributesDisplay> customAttributesDisplays =
391                            new ArrayList<>();
392    
393                    for (Portlet portlet : getPortlets()) {
394                            if (!portlet.isActive() || !portlet.isInclude() ||
395                                    !portlet.isReady() || portlet.isUndeployedPortlet()) {
396    
397                                    continue;
398                            }
399    
400                            List<CustomAttributesDisplay> portletCustomAttributesDisplays =
401                                    portlet.getCustomAttributesDisplayInstances();
402    
403                            if ((portletCustomAttributesDisplays != null) &&
404                                    !portletCustomAttributesDisplays.isEmpty()) {
405    
406                                    customAttributesDisplays.addAll(
407                                            portletCustomAttributesDisplays);
408                            }
409                    }
410    
411                    return customAttributesDisplays;
412            }
413    
414            @Override
415            @Skip
416            public PortletCategory getEARDisplay(String xml) {
417                    try {
418                            return _readLiferayDisplayXML(xml);
419                    }
420                    catch (Exception e) {
421                            throw new SystemException(e);
422                    }
423            }
424    
425            @Override
426            @Skip
427            public List<Portlet> getFriendlyURLMapperPortlets() {
428                    List<Portlet> portlets = new ArrayList<>();
429    
430                    for (Portlet portlet : getPortlets()) {
431                            if (!portlet.isActive() || !portlet.isInclude() ||
432                                    !portlet.isReady() || portlet.isUndeployedPortlet()) {
433    
434                                    continue;
435                            }
436    
437                            FriendlyURLMapper friendlyURLMapper =
438                                    portlet.getFriendlyURLMapperInstance();
439    
440                            if (friendlyURLMapper != null) {
441                                    portlets.add(portlet);
442                            }
443                    }
444    
445                    return portlets;
446            }
447    
448            @Override
449            @Skip
450            public List<FriendlyURLMapper> getFriendlyURLMappers() {
451                    List<FriendlyURLMapper> friendlyURLMappers = new ArrayList<>();
452    
453                    for (Portlet portlet : getPortlets()) {
454                            if (!portlet.isActive() || !portlet.isInclude() ||
455                                    !portlet.isReady() || portlet.isUndeployedPortlet()) {
456    
457                                    continue;
458                            }
459    
460                            FriendlyURLMapper friendlyURLMapper =
461                                    portlet.getFriendlyURLMapperInstance();
462    
463                            if (friendlyURLMapper != null) {
464                                    friendlyURLMappers.add(friendlyURLMapper);
465                            }
466                    }
467    
468                    return friendlyURLMappers;
469            }
470    
471            @Override
472            @Skip
473            public PortletApp getPortletApp(String servletContextName) {
474                    PortletApp portletApp = _portletApps.get(servletContextName);
475    
476                    if (portletApp == null) {
477                            portletApp = new PortletAppImpl(servletContextName);
478    
479                            _portletApps.put(servletContextName, portletApp);
480                    }
481    
482                    return portletApp;
483            }
484    
485            @Override
486            @Skip
487            public Portlet getPortletById(long companyId, String portletId) {
488                    portletId = PortalUtil.getJsSafePortletId(portletId);
489    
490                    Portlet portlet = null;
491    
492                    Map<String, Portlet> companyPortletsMap = _getPortletsMap(companyId);
493    
494                    String rootPortletId = PortletConstants.getRootPortletId(portletId);
495    
496                    if (portletId.equals(rootPortletId)) {
497                            portlet = companyPortletsMap.get(portletId);
498                    }
499                    else {
500                            portlet = companyPortletsMap.get(rootPortletId);
501    
502                            if (portlet != null) {
503                                    portlet = portlet.getClonedInstance(portletId);
504                            }
505                    }
506    
507                    if (portlet != null) {
508                            return portlet;
509                    }
510    
511                    if (portletId.equals(PortletKeys.LIFERAY_PORTAL)) {
512                            return portlet;
513                    }
514    
515                    if (_portletsMap.isEmpty()) {
516                            if (_log.isDebugEnabled()) {
517                                    _log.debug("No portlets are installed");
518                            }
519                    }
520                    else {
521                            if (_log.isInfoEnabled()) {
522                                    _log.info(
523                                            "Portlet not found for " + companyId + " " + portletId);
524                            }
525    
526                            portlet = new PortletImpl(CompanyConstants.SYSTEM, portletId);
527    
528                            PortletApp portletApp = getPortletApp(StringPool.BLANK);
529    
530                            portlet.setPortletApp(portletApp);
531    
532                            portlet.setPortletName(portletId);
533                            portlet.setDisplayName(portletId);
534                            portlet.setPortletClass(UndeployedPortlet.class.getName());
535    
536                            Set<String> mimeTypePortletModes = new HashSet<>();
537    
538                            mimeTypePortletModes.add(
539                                    StringUtil.toLowerCase(PortletMode.VIEW.toString()));
540    
541                            Map<String, Set<String>> portletModes = portlet.getPortletModes();
542    
543                            portletModes.put(ContentTypes.TEXT_HTML, mimeTypePortletModes);
544    
545                            Set<String> mimeTypeWindowStates = new HashSet<>();
546    
547                            mimeTypeWindowStates.add(
548                                    StringUtil.toLowerCase(WindowState.NORMAL.toString()));
549    
550                            Map<String, Set<String>> windowStates = portlet.getWindowStates();
551    
552                            windowStates.put(ContentTypes.TEXT_HTML, mimeTypeWindowStates);
553    
554                            portlet.setPortletInfo(
555                                    new PortletInfo(portletId, portletId, portletId, portletId));
556    
557                            if (PortletConstants.hasInstanceId(portletId)) {
558                                    portlet.setInstanceable(true);
559                            }
560    
561                            portlet.setActive(true);
562                            portlet.setUndeployedPortlet(true);
563                    }
564    
565                    return portlet;
566            }
567    
568            @Override
569            @Skip
570            public Portlet getPortletById(String portletId) {
571                    return _portletsMap.get(PortletConstants.getRootPortletId(portletId));
572            }
573    
574            @Override
575            @Skip
576            public Portlet getPortletByStrutsPath(long companyId, String strutsPath) {
577                    return getPortletById(companyId, _getPortletId(strutsPath));
578            }
579    
580            @Override
581            @Skip
582            public List<Portlet> getPortlets() {
583                    return ListUtil.fromMapValues(_portletsMap);
584            }
585    
586            @Override
587            @Skip
588            public List<Portlet> getPortlets(long companyId) {
589                    return getPortlets(companyId, true, true);
590            }
591    
592            @Override
593            @Skip
594            public List<Portlet> getPortlets(
595                    long companyId, boolean showSystem, boolean showPortal) {
596    
597                    Map<String, Portlet> portletsMap = _getPortletsMap(companyId);
598    
599                    List<Portlet> portlets = ListUtil.fromMapValues(portletsMap);
600    
601                    if (showSystem && showPortal) {
602                            return portlets;
603                    }
604    
605                    Iterator<Portlet> itr = portlets.iterator();
606    
607                    while (itr.hasNext()) {
608                            Portlet portlet = itr.next();
609    
610                            if (showPortal &&
611                                    portlet.getPortletId().equals(PortletKeys.PORTAL)) {
612                            }
613                            else if (!showPortal &&
614                                             portlet.getPortletId().equals(PortletKeys.PORTAL)) {
615    
616                                    itr.remove();
617                            }
618                            else if (!showSystem && portlet.isSystem()) {
619                                    itr.remove();
620                            }
621                    }
622    
623                    return portlets;
624            }
625    
626            @Override
627            @Skip
628            public List<Portlet> getScopablePortlets() {
629                    List<Portlet> portlets = ListUtil.fromMapValues(_portletsMap);
630    
631                    Iterator<Portlet> itr = portlets.iterator();
632    
633                    while (itr.hasNext()) {
634                            Portlet portlet = itr.next();
635    
636                            if (!portlet.isScopeable()) {
637                                    itr.remove();
638                            }
639                    }
640    
641                    return portlets;
642            }
643    
644            @Override
645            @Skip
646            public PortletCategory getWARDisplay(
647                    String servletContextName, String xml) {
648    
649                    try {
650                            return _readLiferayDisplayXML(servletContextName, xml);
651                    }
652                    catch (Exception e) {
653                            throw new SystemException(e);
654                    }
655            }
656    
657            @Override
658            @Skip
659            public boolean hasPortlet(long companyId, String portletId) {
660                    portletId = PortalUtil.getJsSafePortletId(portletId);
661    
662                    Portlet portlet = null;
663    
664                    Map<String, Portlet> companyPortletsMap = _getPortletsMap(companyId);
665    
666                    String rootPortletId = PortletConstants.getRootPortletId(portletId);
667    
668                    if (portletId.equals(rootPortletId)) {
669                            portlet = companyPortletsMap.get(portletId);
670                    }
671                    else {
672                            portlet = companyPortletsMap.get(rootPortletId);
673                    }
674    
675                    if (portlet == null) {
676                            return false;
677                    }
678                    else {
679                            return true;
680                    }
681            }
682    
683            @Override
684            @Skip
685            public void initEAR(
686                    ServletContext servletContext, String[] xmls,
687                    PluginPackage pluginPackage) {
688    
689                    // Clear pools every time initEAR is called. See LEP-5452.
690    
691                    portletLocalService.clearPortletsMap();
692    
693                    _portletApps.clear();
694                    _portletsMap.clear();
695                    _portletIdsByStrutsPath.clear();
696    
697                    try {
698                            PortletApp portletApp = getPortletApp(StringPool.BLANK);
699    
700                            portletApp.setServletContext(servletContext);
701    
702                            Set<String> servletURLPatterns = _readWebXML(xmls[4]);
703    
704                            Map<String, Portlet> portletsMap = _readPortletXML(
705                                    StringPool.BLANK, servletContext, xmls[0], servletURLPatterns,
706                                    pluginPackage);
707    
708                            portletsMap.putAll(
709                                    _readPortletXML(
710                                            StringPool.BLANK, servletContext, xmls[1],
711                                            servletURLPatterns, pluginPackage));
712    
713                            for (Map.Entry<String, Portlet> entry : portletsMap.entrySet()) {
714                                    _portletsMap.put(entry.getKey(), entry.getValue());
715                            }
716    
717                            Set<String> liferayPortletIds = _readLiferayPortletXML(
718                                    StringPool.BLANK, servletContext, xmls[2], portletsMap);
719    
720                            liferayPortletIds.addAll(
721                                    _readLiferayPortletXML(
722                                            StringPool.BLANK, servletContext, xmls[3], portletsMap));
723    
724                            // Check for missing entries in liferay-portlet.xml
725    
726                            for (String portletId : portletsMap.keySet()) {
727                                    if (_log.isWarnEnabled() &&
728                                            !liferayPortletIds.contains(portletId)) {
729    
730                                            _log.warn(
731                                                    "Portlet with the name " + portletId +
732                                                            " is described in portlet.xml but does not " +
733                                                                    "have a matching entry in liferay-portlet.xml");
734                                    }
735                            }
736    
737                            // Check for missing entries in portlet.xml
738    
739                            for (String portletId : liferayPortletIds) {
740                                    if (_log.isWarnEnabled() &&
741                                            !portletsMap.containsKey(portletId)) {
742    
743                                            _log.warn(
744                                                    "Portlet with the name " + portletId +
745                                                            " is described in liferay-portlet.xml but does " +
746                                                                    "not have a matching entry in portlet.xml");
747                                    }
748                            }
749    
750                            // Remove portlets that should not be included
751    
752                            Iterator<Map.Entry<String, Portlet>> portletPoolsItr =
753                                    _portletsMap.entrySet().iterator();
754    
755                            while (portletPoolsItr.hasNext()) {
756                                    Map.Entry<String, Portlet> entry = portletPoolsItr.next();
757    
758                                    Portlet portletModel = entry.getValue();
759    
760                                    String portletId = PortletProviderUtil.getPortletId(
761                                            PortalMyAccountApplicationType.MyAccount.CLASS_NAME,
762                                            PortletProvider.Action.VIEW);
763    
764                                    if (!Validator.equals(
765                                                    portletModel.getPortletId(),
766                                                    PortletKeys.SERVER_ADMIN) &&
767                                            !Validator.equals(portletModel.getPortletId(), portletId) &&
768                                            !portletModel.isInclude()) {
769    
770                                            portletPoolsItr.remove();
771                                    }
772                            }
773    
774                            // Sprite images
775    
776                            _setSpriteImages(servletContext, portletApp, "/html/icons/");
777                    }
778                    catch (Exception e) {
779                            _log.error(e, e);
780                    }
781            }
782    
783            @Override
784            @Skip
785            public List<Portlet> initWAR(
786                    String servletContextName, ServletContext servletContext, String[] xmls,
787                    PluginPackage pluginPackage) {
788    
789                    Map<String, Portlet> portletsMap = null;
790    
791                    Set<String> liferayPortletIds = null;
792    
793                    try {
794                            Set<String> servletURLPatterns = _readWebXML(xmls[3]);
795    
796                            portletsMap = _readPortletXML(
797                                    servletContextName, servletContext, xmls[0], servletURLPatterns,
798                                    pluginPackage);
799    
800                            portletsMap.putAll(
801                                    _readPortletXML(
802                                            servletContextName, servletContext, xmls[1],
803                                            servletURLPatterns, pluginPackage));
804    
805                            liferayPortletIds = _readLiferayPortletXML(
806                                    servletContextName, servletContext, xmls[2], portletsMap);
807                    }
808                    catch (Exception e) {
809                            _log.error(e, e);
810    
811                            return Collections.emptyList();
812                    }
813    
814                    // Check for missing entries in liferay-portlet.xml
815    
816                    for (String portletId : portletsMap.keySet()) {
817                            if (_log.isWarnEnabled() &&
818                                    !liferayPortletIds.contains(portletId)) {
819    
820                                    _log.warn(
821                                            "Portlet with the name " + portletId +
822                                                    " is described in portlet.xml but does not " +
823                                                            "have a matching entry in liferay-portlet.xml");
824                            }
825                    }
826    
827                    // Check for missing entries in portlet.xml
828    
829                    for (String portletId : liferayPortletIds) {
830                            if (_log.isWarnEnabled() && !portletsMap.containsKey(portletId)) {
831                                    _log.warn(
832                                            "Portlet with the name " + portletId +
833                                                    " is described in liferay-portlet.xml but does " +
834                                                            "not have a matching entry in portlet.xml");
835                            }
836                    }
837    
838                    PortletBagFactory portletBagFactory = new PortletBagFactory();
839    
840                    portletBagFactory.setClassLoader(
841                            ClassLoaderPool.getClassLoader(servletContextName));
842                    portletBagFactory.setServletContext(servletContext);
843                    portletBagFactory.setWARFile(true);
844    
845                    // Return the new portlets
846    
847                    try {
848                            for (Map.Entry<String, Portlet> entry : portletsMap.entrySet()) {
849                                    Portlet portlet = _portletsMap.remove(entry.getKey());
850    
851                                    if (portlet != null) {
852                                            PortletInstanceFactoryUtil.clear(portlet);
853    
854                                            PortletConfigFactoryUtil.destroy(portlet);
855                                            PortletContextFactory.destroy(portlet);
856                                    }
857    
858                                    portlet = entry.getValue();
859    
860                                    _portletsMap.put(entry.getKey(), portlet);
861    
862                                    portletBagFactory.create(portlet);
863                            }
864    
865                            // Sprite images
866    
867                            PortletApp portletApp = getPortletApp(servletContextName);
868    
869                            _setSpriteImages(servletContext, portletApp, "/icons/");
870    
871                            return ListUtil.fromMapValues(portletsMap);
872                    }
873                    catch (Exception e) {
874                            _log.error(e, e);
875    
876                            // Clean up portlets added prior to error
877    
878                            for (Map.Entry<String, Portlet> entry : portletsMap.entrySet()) {
879                                    Portlet portlet = _portletsMap.remove(entry.getKey());
880    
881                                    if (portlet != null) {
882                                            PortletInstanceFactoryUtil.clear(portlet);
883    
884                                            PortletConfigFactoryUtil.destroy(portlet);
885                                            PortletContextFactory.destroy(portlet);
886                                    }
887                            }
888    
889                            return Collections.emptyList();
890                    }
891                    finally {
892                            clearCache();
893                    }
894            }
895    
896            @Override
897            public Map<String, Portlet> loadGetPortletsMap(long companyId) {
898                    Map<String, Portlet> portletsMap = new ConcurrentHashMap<>();
899    
900                    for (Portlet portlet : _portletsMap.values()) {
901                            portlet = (Portlet)portlet.clone();
902    
903                            portlet.setCompanyId(companyId);
904    
905                            portletsMap.put(portlet.getPortletId(), portlet);
906                    }
907    
908                    List<Portlet> portlets = portletPersistence.findByCompanyId(companyId);
909    
910                    for (Portlet portlet : portlets) {
911                            Portlet portletModel = portletsMap.get(portlet.getPortletId());
912    
913                            // Portlet may be null if it exists in the database but its portlet
914                            // WAR is not yet loaded
915    
916                            if (portletModel != null) {
917                                    portletModel.setPluginPackage(portlet.getPluginPackage());
918                                    portletModel.setDefaultPluginSetting(
919                                            portlet.getDefaultPluginSetting());
920                                    portletModel.setRoles(portlet.getRoles());
921                                    portletModel.setActive(portlet.getActive());
922                            }
923                    }
924    
925                    return portletsMap;
926            }
927    
928            /**
929             * @deprecated As of 7.0.0, replaced by {@link #loadGetPortletsMap(long))}
930             */
931            @Deprecated
932            @Override
933            public Map<String, Portlet> loadGetPortletsPool(long companyId) {
934                    return loadGetPortletsMap(companyId);
935            }
936    
937            @Clusterable
938            @Override
939            @Transactional(enabled = false)
940            public void removeCompanyPortletsPool(long companyId) {
941                    _portletsMaps.remove(companyId);
942            }
943    
944            @Override
945            public Portlet updatePortlet(
946                    long companyId, String portletId, String roles, boolean active) {
947    
948                    portletId = PortalUtil.getJsSafePortletId(portletId);
949    
950                    Portlet portlet = portletPersistence.fetchByC_P(companyId, portletId);
951    
952                    if (portlet == null) {
953                            long id = counterLocalService.increment();
954    
955                            portlet = portletPersistence.create(id);
956    
957                            portlet.setCompanyId(companyId);
958                            portlet.setPortletId(portletId);
959                    }
960    
961                    portlet.setRoles(roles);
962                    portlet.setActive(active);
963    
964                    portletPersistence.update(portlet);
965    
966                    portlet = getPortletById(companyId, portletId);
967    
968                    portlet.setRoles(roles);
969                    portlet.setActive(active);
970    
971                    portletLocalService.removeCompanyPortletsPool(companyId);
972    
973                    return portlet;
974            }
975    
976            private String _getPortletId(String securityPath) {
977                    if (_portletIdsByStrutsPath.isEmpty()) {
978                            for (Portlet portlet : _portletsMap.values()) {
979                                    String strutsPath = portlet.getStrutsPath();
980    
981                                    if (_portletIdsByStrutsPath.containsKey(strutsPath)) {
982                                            if (_log.isWarnEnabled()) {
983                                                    _log.warn("Duplicate struts path " + strutsPath);
984                                            }
985                                    }
986    
987                                    _portletIdsByStrutsPath.put(strutsPath, portlet.getPortletId());
988                            }
989                    }
990    
991                    String portletId = _portletIdsByStrutsPath.get(securityPath);
992    
993                    if (Validator.isNull(portletId)) {
994                            for (String strutsPath : _portletIdsByStrutsPath.keySet()) {
995                                    if (securityPath.startsWith(
996                                                    strutsPath.concat(StringPool.SLASH))) {
997    
998                                            portletId = _portletIdsByStrutsPath.get(strutsPath);
999    
1000                                            break;
1001                                    }
1002                            }
1003                    }
1004    
1005                    if (Validator.isNull(portletId)) {
1006                            _log.error(
1007                                    "Struts path " + securityPath + " is not mapped to a portlet " +
1008                                            "in liferay-portlet.xml");
1009                    }
1010    
1011                    return portletId;
1012            }
1013    
1014            private List<Portlet> _getPortletsByPortletName(
1015                    String portletName, String servletContextName,
1016                    Map<String, Portlet> portletsMap) {
1017    
1018                    int pos = portletName.indexOf(CharPool.STAR);
1019    
1020                    if (pos == -1) {
1021                            String portletId = portletName;
1022    
1023                            if (Validator.isNotNull(servletContextName)) {
1024                                    portletId =
1025                                            portletId + PortletConstants.WAR_SEPARATOR +
1026                                                    servletContextName;
1027                            }
1028    
1029                            portletId = PortalUtil.getJsSafePortletId(portletId);
1030    
1031                            Portlet portlet = portletsMap.get(portletId);
1032    
1033                            if (portlet == null) {
1034                                    return Collections.emptyList();
1035                            }
1036    
1037                            return Collections.singletonList(portlet);
1038                    }
1039    
1040                    return _getPortletsByServletContextName(
1041                            servletContextName, portletName.substring(0, pos), portletsMap);
1042            }
1043    
1044            private List<Portlet> _getPortletsByServletContextName(
1045                    String servletContextName, String portletNamePrefix,
1046                    Map<String, Portlet> portletsMap) {
1047    
1048                    List<Portlet> portlets = new ArrayList<>();
1049    
1050                    String servletContextNameSuffix = null;
1051    
1052                    if (Validator.isNotNull(servletContextName)) {
1053                            servletContextNameSuffix = PortalUtil.getJsSafePortletId(
1054                                    PortletConstants.WAR_SEPARATOR.concat(servletContextName));
1055                    }
1056    
1057                    for (Map.Entry<String, Portlet> entry : portletsMap.entrySet()) {
1058                            String portletId = entry.getKey();
1059    
1060                            if (!portletId.startsWith(portletNamePrefix)) {
1061                                    continue;
1062                            }
1063    
1064                            if (servletContextNameSuffix == null) {
1065                                    if (!portletId.contains(PortletConstants.WAR_SEPARATOR)) {
1066                                            portlets.add(entry.getValue());
1067                                    }
1068                            }
1069                            else if (portletId.endsWith(servletContextNameSuffix)) {
1070                                    portlets.add(entry.getValue());
1071                            }
1072                    }
1073    
1074                    return portlets;
1075            }
1076    
1077            private Map<String, Portlet> _getPortletsMap(long companyId) {
1078                    Map<String, Portlet> portletsMap = _portletsMaps.get(companyId);
1079    
1080                    if (portletsMap == null) {
1081                            portletsMap = portletLocalService.loadGetPortletsMap(companyId);
1082    
1083                            _portletsMaps.put(companyId, portletsMap);
1084                    }
1085    
1086                    return portletsMap;
1087            }
1088    
1089            private String _getTriggerValue(Portlet portlet, String propertyKey) {
1090                    PortletApp portletApp = portlet.getPortletApp();
1091    
1092                    ServletContext servletContext = portletApp.getServletContext();
1093    
1094                    ClassLoader classLoader = servletContext.getClassLoader();
1095    
1096                    Configuration configuration = _propertiesConfigurations.get(
1097                            classLoader);
1098    
1099                    if (configuration == null) {
1100                            String propertyFileName = "portal";
1101    
1102                            if (portletApp.isWARFile()) {
1103                                    propertyFileName = "portlet";
1104                            }
1105    
1106                            configuration = ConfigurationFactoryUtil.getConfiguration(
1107                                    classLoader, propertyFileName);
1108    
1109                            _propertiesConfigurations.put(classLoader, configuration);
1110                    }
1111    
1112                    return configuration.get(propertyKey);
1113            }
1114    
1115            private void _readLiferayDisplay(
1116                    String servletContextName, Element element,
1117                    PortletCategory portletCategory, Set<String> portletIds) {
1118    
1119                    for (Element categoryElement : element.elements("category")) {
1120                            String name = categoryElement.attributeValue("name");
1121    
1122                            PortletCategory curPortletCategory = new PortletCategory(name);
1123    
1124                            portletCategory.addCategory(curPortletCategory);
1125    
1126                            Set<String> curPortletIds = curPortletCategory.getPortletIds();
1127    
1128                            for (Element portletElement : categoryElement.elements("portlet")) {
1129                                    String portletId = portletElement.attributeValue("id");
1130    
1131                                    if (Validator.isNotNull(servletContextName)) {
1132                                            portletId =
1133                                                    portletId + PortletConstants.WAR_SEPARATOR +
1134                                                            servletContextName;
1135                                    }
1136    
1137                                    portletId = PortalUtil.getJsSafePortletId(portletId);
1138    
1139                                    portletIds.add(portletId);
1140                                    curPortletIds.add(portletId);
1141                            }
1142    
1143                            _readLiferayDisplay(
1144                                    servletContextName, categoryElement, curPortletCategory,
1145                                    portletIds);
1146                    }
1147            }
1148    
1149            private PortletCategory _readLiferayDisplayXML(String xml)
1150                    throws Exception {
1151    
1152                    return _readLiferayDisplayXML(null, xml);
1153            }
1154    
1155            private PortletCategory _readLiferayDisplayXML(
1156                            String servletContextName, String xml)
1157                    throws Exception {
1158    
1159                    PortletCategory portletCategory = new PortletCategory();
1160    
1161                    if (xml == null) {
1162                            xml = ContentUtil.get(
1163                                    "com/liferay/portal/deploy/dependencies/liferay-display.xml");
1164                    }
1165    
1166                    Document document = UnsecureSAXReaderUtil.read(xml, true);
1167    
1168                    Element rootElement = document.getRootElement();
1169    
1170                    Set<String> portletIds = new HashSet<>();
1171    
1172                    _readLiferayDisplay(
1173                            servletContextName, rootElement, portletCategory, portletIds);
1174    
1175                    // Portlets that do not belong to any categories should default to the
1176                    // Undefined category
1177    
1178                    Set<String> undefinedPortletIds = new HashSet<>();
1179    
1180                    for (Portlet portlet : _portletsMap.values()) {
1181                            String portletId = portlet.getPortletId();
1182    
1183                            PortletApp portletApp = portlet.getPortletApp();
1184    
1185                            if ((servletContextName != null) && portletApp.isWARFile() &&
1186                                    portletId.endsWith(
1187                                            PortletConstants.WAR_SEPARATOR +
1188                                                    PortalUtil.getJsSafePortletId(servletContextName)) &&
1189                                    !portletIds.contains(portletId)) {
1190    
1191                                    undefinedPortletIds.add(portletId);
1192                            }
1193                            else if ((servletContextName == null) && !portletApp.isWARFile() &&
1194                                             !portletId.contains(PortletConstants.WAR_SEPARATOR) &&
1195                                             !portletIds.contains(portletId)) {
1196    
1197                                    undefinedPortletIds.add(portletId);
1198                            }
1199                    }
1200    
1201                    if (!undefinedPortletIds.isEmpty()) {
1202                            PortletCategory undefinedCategory = new PortletCategory(
1203                                    "category.undefined");
1204    
1205                            portletCategory.addCategory(undefinedCategory);
1206    
1207                            undefinedCategory.getPortletIds().addAll(undefinedPortletIds);
1208                    }
1209    
1210                    return portletCategory;
1211            }
1212    
1213            private void _readLiferayPortletXML(
1214                    String servletContextName, ServletContext servletContext,
1215                    Set<String> liferayPortletIds, Map<String, String> roleMappers,
1216                    Element portletElement, Map<String, Portlet> portletsMap) {
1217    
1218                    String portletId = portletElement.elementText("portlet-name");
1219    
1220                    if (Validator.isNotNull(servletContextName)) {
1221                            portletId = portletId.concat(PortletConstants.WAR_SEPARATOR).concat(
1222                                    servletContextName);
1223                    }
1224    
1225                    portletId = PortalUtil.getJsSafePortletId(portletId);
1226    
1227                    if (_log.isDebugEnabled()) {
1228                            _log.debug("Reading portlet extension " + portletId);
1229                    }
1230    
1231                    liferayPortletIds.add(portletId);
1232    
1233                    Portlet portletModel = portletsMap.get(portletId);
1234    
1235                    if (portletModel == null) {
1236                            return;
1237                    }
1238    
1239                    portletModel.setIcon(
1240                            GetterUtil.getString(
1241                                    portletElement.elementText("icon"), portletModel.getIcon()));
1242                    portletModel.setVirtualPath(
1243                            GetterUtil.getString(
1244                                    portletElement.elementText("virtual-path"),
1245                                    portletModel.getVirtualPath()));
1246                    portletModel.setStrutsPath(
1247                            GetterUtil.getString(
1248                                    portletElement.elementText("struts-path"),
1249                                    portletModel.getStrutsPath()));
1250    
1251                    String strutsPath = portletModel.getStrutsPath();
1252    
1253                    if (Validator.isNotNull(strutsPath)) {
1254                            if (_portletIdsByStrutsPath.containsKey(strutsPath)) {
1255                                    String strutsPathPortletId = _portletIdsByStrutsPath.get(
1256                                            strutsPath);
1257    
1258                                    if (!strutsPathPortletId.equals(portletId)) {
1259                                            if (_log.isWarnEnabled()) {
1260                                                    _log.warn("Duplicate struts path " + strutsPath);
1261                                            }
1262                                    }
1263                            }
1264    
1265                            _portletIdsByStrutsPath.put(strutsPath, portletId);
1266                    }
1267    
1268                    portletModel.setParentStrutsPath(
1269                            GetterUtil.getString(
1270                                    portletElement.elementText("parent-struts-path"),
1271                                    portletModel.getParentStrutsPath()));
1272    
1273                    if (Validator.isNotNull(
1274                                    portletElement.elementText("configuration-path"))) {
1275    
1276                            _log.error(
1277                                    "The configuration-path element is no longer supported. Use " +
1278                                            "configuration-action-class instead.");
1279                    }
1280    
1281                    portletModel.setConfigurationActionClass(
1282                            GetterUtil.getString(
1283                                    portletElement.elementText("configuration-action-class"),
1284                                    portletModel.getConfigurationActionClass()));
1285    
1286                    List<String> indexerClasses = new ArrayList<>();
1287    
1288                    for (Element indexerClassElement :
1289                                    portletElement.elements("indexer-class")) {
1290    
1291                            indexerClasses.add(indexerClassElement.getText());
1292                    }
1293    
1294                    portletModel.setIndexerClasses(indexerClasses);
1295    
1296                    portletModel.setOpenSearchClass(
1297                            GetterUtil.getString(
1298                                    portletElement.elementText("open-search-class"),
1299                                    portletModel.getOpenSearchClass()));
1300    
1301                    for (Element schedulerEntryElement :
1302                                    portletElement.elements("scheduler-entry")) {
1303    
1304                            SchedulerEntryImpl schedulerEntryImpl = new SchedulerEntryImpl();
1305    
1306                            String description = GetterUtil.getString(
1307                                    schedulerEntryElement.elementText("scheduler-description"));
1308    
1309                            schedulerEntryImpl.setDescription(description);
1310    
1311                            String eventListenerClass = GetterUtil.getString(
1312                                    schedulerEntryElement.elementText(
1313                                            "scheduler-event-listener-class"));
1314    
1315                            schedulerEntryImpl.setEventListenerClass(eventListenerClass);
1316    
1317                            Element triggerElement = schedulerEntryElement.element("trigger");
1318    
1319                            Element cronElement = triggerElement.element("cron");
1320                            Element simpleElement = triggerElement.element("simple");
1321    
1322                            if (cronElement != null) {
1323                                    Element propertyKeyElement = cronElement.element(
1324                                            "property-key");
1325    
1326                                    String cronException = null;
1327    
1328                                    if (propertyKeyElement != null) {
1329                                            cronException = _getTriggerValue(
1330                                                    portletModel, propertyKeyElement.getTextTrim());
1331                                    }
1332                                    else {
1333                                            cronException = cronElement.elementText(
1334                                                    "cron-trigger-value");
1335                                    }
1336    
1337                                    schedulerEntryImpl.setTrigger(
1338                                            TriggerFactoryUtil.createTrigger(
1339                                                    eventListenerClass, eventListenerClass, cronException));
1340                            }
1341                            else if (simpleElement != null) {
1342                                    Element propertyKeyElement = simpleElement.element(
1343                                            "property-key");
1344    
1345                                    String intervalString = null;
1346    
1347                                    if (propertyKeyElement != null) {
1348                                            intervalString = _getTriggerValue(
1349                                                    portletModel, propertyKeyElement.getTextTrim());
1350                                    }
1351                                    else {
1352                                            Element simpleTriggerValueElement = simpleElement.element(
1353                                                    "simple-trigger-value");
1354    
1355                                            intervalString = simpleTriggerValueElement.getTextTrim();
1356                                    }
1357    
1358                                    String timeUnitString = StringUtil.toUpperCase(
1359                                            GetterUtil.getString(
1360                                                    simpleElement.elementText("time-unit"),
1361                                                    TimeUnit.SECOND.getValue()));
1362    
1363                                    schedulerEntryImpl.setTrigger(
1364                                            TriggerFactoryUtil.createTrigger(
1365                                                    eventListenerClass, eventListenerClass,
1366                                                    GetterUtil.getIntegerStrict(intervalString),
1367                                                    TimeUnit.valueOf(timeUnitString)));
1368                            }
1369    
1370                            portletModel.addSchedulerEntry(schedulerEntryImpl);
1371                    }
1372    
1373                    portletModel.setPortletURLClass(
1374                            GetterUtil.getString(
1375                                    portletElement.elementText("portlet-url-class"),
1376                                    portletModel.getPortletURLClass()));
1377                    portletModel.setFriendlyURLMapperClass(
1378                            GetterUtil.getString(
1379                                    portletElement.elementText("friendly-url-mapper-class"),
1380                                    portletModel.getFriendlyURLMapperClass()));
1381                    portletModel.setFriendlyURLMapping(
1382                            GetterUtil.getString(
1383                                    portletElement.elementText("friendly-url-mapping"),
1384                                    portletModel.getFriendlyURLMapping()));
1385                    portletModel.setFriendlyURLRoutes(
1386                            GetterUtil.getString(
1387                                    portletElement.elementText("friendly-url-routes"),
1388                                    portletModel.getFriendlyURLRoutes()));
1389                    portletModel.setURLEncoderClass(
1390                            GetterUtil.getString(
1391                                    portletElement.elementText("url-encoder-class"),
1392                                    portletModel.getURLEncoderClass()));
1393                    portletModel.setPortletDataHandlerClass(
1394                            GetterUtil.getString(
1395                                    portletElement.elementText("portlet-data-handler-class"),
1396                                    portletModel.getPortletDataHandlerClass()));
1397    
1398                    List<String> stagedModelDataHandlerClasses = new ArrayList<>();
1399    
1400                    for (Element stagedModelDataHandlerClassElement :
1401                                    portletElement.elements("staged-model-data-handler-class")) {
1402    
1403                            stagedModelDataHandlerClasses.add(
1404                                    stagedModelDataHandlerClassElement.getText());
1405                    }
1406    
1407                    portletModel.setStagedModelDataHandlerClasses(
1408                            stagedModelDataHandlerClasses);
1409    
1410                    portletModel.setTemplateHandlerClass(
1411                            GetterUtil.getString(
1412                                    portletElement.elementText("template-handler"),
1413                                    portletModel.getTemplateHandlerClass()));
1414                    portletModel.setPortletLayoutListenerClass(
1415                            GetterUtil.getString(
1416                                    portletElement.elementText("portlet-layout-listener-class"),
1417                                    portletModel.getPortletLayoutListenerClass()));
1418                    portletModel.setPollerProcessorClass(
1419                            GetterUtil.getString(
1420                                    portletElement.elementText("poller-processor-class"),
1421                                    portletModel.getPollerProcessorClass()));
1422                    portletModel.setPopMessageListenerClass(
1423                            GetterUtil.getString(
1424                                    portletElement.elementText("pop-message-listener-class"),
1425                                    portletModel.getPopMessageListenerClass()));
1426    
1427                    List<String> socialActivityInterpreterClasses = new ArrayList<>();
1428    
1429                    for (Element socialActivityInterpreterClassElement :
1430                                    portletElement.elements("social-activity-interpreter-class")) {
1431    
1432                            socialActivityInterpreterClasses.add(
1433                                    socialActivityInterpreterClassElement.getText());
1434                    }
1435    
1436                    portletModel.setSocialActivityInterpreterClasses(
1437                            socialActivityInterpreterClasses);
1438    
1439                    portletModel.setSocialRequestInterpreterClass(
1440                            GetterUtil.getString(
1441                                    portletElement.elementText("social-request-interpreter-class"),
1442                                    portletModel.getSocialRequestInterpreterClass()));
1443                    portletModel.setUserNotificationDefinitions(
1444                            GetterUtil.getString(
1445                                    portletElement.elementText("user-notification-definitions"),
1446                                    portletModel.getUserNotificationDefinitions()));
1447    
1448                    List<String> userNotificationHandlerClasses = new ArrayList<>();
1449    
1450                    for (Element userNotificationHandlerClassElement :
1451                                    portletElement.elements(
1452                                            "user-notification-handler-class")) {
1453    
1454                            userNotificationHandlerClasses.add(
1455                                    userNotificationHandlerClassElement.getText());
1456                    }
1457    
1458                    portletModel.setUserNotificationHandlerClasses(
1459                            userNotificationHandlerClasses);
1460    
1461                    portletModel.setWebDAVStorageToken(
1462                            GetterUtil.getString(
1463                                    portletElement.elementText("webdav-storage-token"),
1464                                    portletModel.getWebDAVStorageToken()));
1465                    portletModel.setWebDAVStorageClass(
1466                            GetterUtil.getString(
1467                                    portletElement.elementText("webdav-storage-class"),
1468                                    portletModel.getWebDAVStorageClass()));
1469                    portletModel.setXmlRpcMethodClass(
1470                            GetterUtil.getString(
1471                                    portletElement.elementText("xml-rpc-method-class"),
1472                                    portletModel.getXmlRpcMethodClass()));
1473    
1474                    Set<ApplicationType> applicationTypes = new HashSet<>();
1475    
1476                    for (Element applicationTypeElement :
1477                                    portletElement.elements("application-type")) {
1478    
1479                            try {
1480                                    applicationTypes.add(
1481                                            ApplicationType.parse(applicationTypeElement.getText()));
1482                            }
1483                            catch (IllegalArgumentException iae) {
1484                                    if (_log.isWarnEnabled()) {
1485                                            _log.warn(
1486                                                    "Unknown application type " +
1487                                                            applicationTypeElement.getText());
1488                                    }
1489                            }
1490                    }
1491    
1492                    if (applicationTypes.isEmpty()) {
1493                            applicationTypes.add(ApplicationType.WIDGET);
1494                    }
1495    
1496                    portletModel.setApplicationTypes(applicationTypes);
1497    
1498                    portletModel.setControlPanelEntryClass(
1499                            GetterUtil.getString(
1500                                    portletElement.elementText("control-panel-entry-class"),
1501                                    portletModel.getControlPanelEntryClass()));
1502    
1503                    List<String> assetRendererFactoryClasses = new ArrayList<>();
1504    
1505                    for (Element assetRendererFactoryClassElement :
1506                                    portletElement.elements("asset-renderer-factory")) {
1507    
1508                            assetRendererFactoryClasses.add(
1509                                    assetRendererFactoryClassElement.getText());
1510                    }
1511    
1512                    portletModel.setAssetRendererFactoryClasses(
1513                            assetRendererFactoryClasses);
1514    
1515                    List<String> atomCollectionAdapterClasses = new ArrayList<>();
1516    
1517                    for (Element atomCollectionAdapterClassElement :
1518                                    portletElement.elements("atom-collection-adapter")) {
1519    
1520                            atomCollectionAdapterClasses.add(
1521                                    atomCollectionAdapterClassElement.getText());
1522                    }
1523    
1524                    portletModel.setAtomCollectionAdapterClasses(
1525                            atomCollectionAdapterClasses);
1526    
1527                    List<String> customAttributesDisplayClasses = new ArrayList<>();
1528    
1529                    for (Element customAttributesDisplayClassElement :
1530                                    portletElement.elements("custom-attributes-display")) {
1531    
1532                            customAttributesDisplayClasses.add(
1533                                    customAttributesDisplayClassElement.getText());
1534                    }
1535    
1536                    portletModel.setCustomAttributesDisplayClasses(
1537                            customAttributesDisplayClasses);
1538    
1539                    portletModel.setPermissionPropagatorClass(
1540                            GetterUtil.getString(
1541                                    portletElement.elementText("permission-propagator"),
1542                                    portletModel.getPermissionPropagatorClass()));
1543    
1544                    List<String> trashHandlerClasses = new ArrayList<>();
1545    
1546                    for (Element trashHandlerClassElement :
1547                                    portletElement.elements("trash-handler")) {
1548    
1549                            trashHandlerClasses.add(trashHandlerClassElement.getText());
1550                    }
1551    
1552                    portletModel.setTrashHandlerClasses(trashHandlerClasses);
1553    
1554                    List<String> workflowHandlerClasses = new ArrayList<>();
1555    
1556                    for (Element workflowHandlerClassElement :
1557                                    portletElement.elements("workflow-handler")) {
1558    
1559                            workflowHandlerClasses.add(workflowHandlerClassElement.getText());
1560                    }
1561    
1562                    portletModel.setWorkflowHandlerClasses(workflowHandlerClasses);
1563    
1564                    portletModel.setPreferencesCompanyWide(
1565                            GetterUtil.getBoolean(
1566                                    portletElement.elementText("preferences-company-wide"),
1567                                    portletModel.isPreferencesCompanyWide()));
1568                    portletModel.setPreferencesUniquePerLayout(
1569                            GetterUtil.getBoolean(
1570                                    portletElement.elementText("preferences-unique-per-layout"),
1571                                    portletModel.isPreferencesUniquePerLayout()));
1572                    portletModel.setPreferencesOwnedByGroup(
1573                            GetterUtil.getBoolean(
1574                                    portletElement.elementText("preferences-owned-by-group"),
1575                                    portletModel.isPreferencesOwnedByGroup()));
1576                    portletModel.setUseDefaultTemplate(
1577                            GetterUtil.getBoolean(
1578                                    portletElement.elementText("use-default-template"),
1579                                    portletModel.isUseDefaultTemplate()));
1580                    portletModel.setShowPortletAccessDenied(
1581                            GetterUtil.getBoolean(
1582                                    portletElement.elementText("show-portlet-access-denied"),
1583                                    portletModel.isShowPortletAccessDenied()));
1584                    portletModel.setShowPortletInactive(
1585                            GetterUtil.getBoolean(
1586                                    portletElement.elementText("show-portlet-inactive"),
1587                                    portletModel.isShowPortletInactive()));
1588                    portletModel.setActionURLRedirect(
1589                            GetterUtil.getBoolean(
1590                                    portletElement.elementText("action-url-redirect"),
1591                                    portletModel.isActionURLRedirect()));
1592                    portletModel.setRestoreCurrentView(
1593                            GetterUtil.getBoolean(
1594                                    portletElement.elementText("restore-current-view"),
1595                                    portletModel.isRestoreCurrentView()));
1596                    portletModel.setMaximizeEdit(
1597                            GetterUtil.getBoolean(
1598                                    portletElement.elementText("maximize-edit"),
1599                                    portletModel.isMaximizeEdit()));
1600                    portletModel.setMaximizeHelp(
1601                            GetterUtil.getBoolean(
1602                                    portletElement.elementText("maximize-help"),
1603                                    portletModel.isMaximizeHelp()));
1604                    portletModel.setPopUpPrint(
1605                            GetterUtil.getBoolean(
1606                                    portletElement.elementText("pop-up-print"),
1607                                    portletModel.isPopUpPrint()));
1608                    portletModel.setLayoutCacheable(
1609                            GetterUtil.getBoolean(
1610                                    portletElement.elementText("layout-cacheable"),
1611                                    portletModel.isLayoutCacheable()));
1612                    portletModel.setInstanceable(
1613                            GetterUtil.getBoolean(
1614                                    portletElement.elementText("instanceable"),
1615                                    portletModel.isInstanceable()));
1616                    portletModel.setRemoteable(
1617                            GetterUtil.getBoolean(
1618                                    portletElement.elementText("remoteable"),
1619                                    portletModel.isRemoteable()));
1620                    portletModel.setScopeable(
1621                            GetterUtil.getBoolean(
1622                                    portletElement.elementText("scopeable"),
1623                                    portletModel.isScopeable()));
1624                    portletModel.setSinglePageApplication(
1625                            GetterUtil.getBoolean(
1626                                    portletElement.elementText("single-page-application"),
1627                                    portletModel.isSinglePageApplication()));
1628                    portletModel.setUserPrincipalStrategy(
1629                            GetterUtil.getString(
1630                                    portletElement.elementText("user-principal-strategy"),
1631                                    portletModel.getUserPrincipalStrategy()));
1632                    portletModel.setPrivateRequestAttributes(
1633                            GetterUtil.getBoolean(
1634                                    portletElement.elementText("private-request-attributes"),
1635                                    portletModel.isPrivateRequestAttributes()));
1636                    portletModel.setPrivateSessionAttributes(
1637                            GetterUtil.getBoolean(
1638                                    portletElement.elementText("private-session-attributes"),
1639                                    portletModel.isPrivateSessionAttributes()));
1640    
1641                    Element autopropagatedParametersElement = portletElement.element(
1642                            "autopropagated-parameters");
1643    
1644                    Set<String> autopropagatedParameters = new HashSet<>();
1645    
1646                    if (autopropagatedParametersElement != null) {
1647                            String[] autopropagatedParametersArray = StringUtil.split(
1648                                    autopropagatedParametersElement.getText());
1649    
1650                            for (String autopropagatedParameter :
1651                                            autopropagatedParametersArray) {
1652    
1653                                    autopropagatedParameters.add(autopropagatedParameter);
1654                            }
1655                    }
1656    
1657                    portletModel.setAutopropagatedParameters(autopropagatedParameters);
1658    
1659                    boolean defaultRequiresNamespacedParameters = GetterUtil.getBoolean(
1660                            servletContext.getInitParameter(
1661                                    "com.liferay.portlet.requires-namespaced-parameters"),
1662                            portletModel.isRequiresNamespacedParameters());
1663    
1664                    portletModel.setRequiresNamespacedParameters(
1665                            GetterUtil.getBoolean(
1666                                    portletElement.elementText("requires-namespaced-parameters"),
1667                                    defaultRequiresNamespacedParameters));
1668    
1669                    portletModel.setActionTimeout(
1670                            GetterUtil.getInteger(
1671                                    portletElement.elementText("action-timeout"),
1672                                    portletModel.getActionTimeout()));
1673                    portletModel.setRenderTimeout(
1674                            GetterUtil.getInteger(
1675                                    portletElement.elementText("render-timeout"),
1676                                    portletModel.getRenderTimeout()));
1677                    portletModel.setRenderWeight(
1678                            GetterUtil.getInteger(
1679                                    portletElement.elementText("render-weight"),
1680                                    portletModel.getRenderWeight()));
1681                    portletModel.setAjaxable(
1682                            GetterUtil.getBoolean(
1683                                    portletElement.elementText("ajaxable"),
1684                                    portletModel.isAjaxable()));
1685    
1686                    List<String> headerPortalCssList = new ArrayList<>();
1687    
1688                    for (Element headerPortalCssElement :
1689                                    portletElement.elements("header-portal-css")) {
1690    
1691                            headerPortalCssList.add(headerPortalCssElement.getText());
1692                    }
1693    
1694                    portletModel.setHeaderPortalCss(headerPortalCssList);
1695    
1696                    List<String> headerPortletCssList = new ArrayList<>();
1697    
1698                    for (Element headerPortletCssElement :
1699                                    portletElement.elements("header-portlet-css")) {
1700    
1701                            headerPortletCssList.add(headerPortletCssElement.getText());
1702                    }
1703    
1704                    portletModel.setHeaderPortletCss(headerPortletCssList);
1705    
1706                    List<String> headerPortalJavaScriptList = new ArrayList<>();
1707    
1708                    for (Element headerPortalJavaScriptElement :
1709                                    portletElement.elements("header-portal-javascript")) {
1710    
1711                            headerPortalJavaScriptList.add(
1712                                    headerPortalJavaScriptElement.getText());
1713                    }
1714    
1715                    portletModel.setHeaderPortalJavaScript(headerPortalJavaScriptList);
1716    
1717                    List<String> headerPortletJavaScriptList = new ArrayList<>();
1718    
1719                    for (Element headerPortletJavaScriptElement :
1720                                    portletElement.elements("header-portlet-javascript")) {
1721    
1722                            headerPortletJavaScriptList.add(
1723                                    headerPortletJavaScriptElement.getText());
1724                    }
1725    
1726                    portletModel.setHeaderPortletJavaScript(headerPortletJavaScriptList);
1727    
1728                    List<String> footerPortalCssList = new ArrayList<>();
1729    
1730                    for (Element footerPortalCssElement :
1731                                    portletElement.elements("footer-portal-css")) {
1732    
1733                            footerPortalCssList.add(footerPortalCssElement.getText());
1734                    }
1735    
1736                    portletModel.setFooterPortalCss(footerPortalCssList);
1737    
1738                    List<String> footerPortletCssList = new ArrayList<>();
1739    
1740                    for (Element footerPortletCssElement :
1741                                    portletElement.elements("footer-portlet-css")) {
1742    
1743                            footerPortletCssList.add(footerPortletCssElement.getText());
1744                    }
1745    
1746                    portletModel.setFooterPortletCss(footerPortletCssList);
1747    
1748                    List<String> footerPortalJavaScriptList = new ArrayList<>();
1749    
1750                    for (Element footerPortalJavaScriptElement :
1751                                    portletElement.elements("footer-portal-javascript")) {
1752    
1753                            footerPortalJavaScriptList.add(
1754                                    footerPortalJavaScriptElement.getText());
1755                    }
1756    
1757                    portletModel.setFooterPortalJavaScript(footerPortalJavaScriptList);
1758    
1759                    List<String> footerPortletJavaScriptList = new ArrayList<>();
1760    
1761                    for (Element footerPortletJavaScriptElement :
1762                                    portletElement.elements("footer-portlet-javascript")) {
1763    
1764                            footerPortletJavaScriptList.add(
1765                                    footerPortletJavaScriptElement.getText());
1766                    }
1767    
1768                    portletModel.setFooterPortletJavaScript(footerPortletJavaScriptList);
1769    
1770                    portletModel.setCssClassWrapper(
1771                            GetterUtil.getString(
1772                                    portletElement.elementText("css-class-wrapper"),
1773                                    portletModel.getCssClassWrapper()));
1774                    portletModel.setFacebookIntegration(
1775                            GetterUtil.getString(
1776                                    portletElement.elementText("facebook-integration"),
1777                                    portletModel.getFacebookIntegration()));
1778                    portletModel.setAddDefaultResource(
1779                            GetterUtil.getBoolean(
1780                                    portletElement.elementText("add-default-resource"),
1781                                    portletModel.isAddDefaultResource()));
1782                    portletModel.setSystem(
1783                            GetterUtil.getBoolean(
1784                                    portletElement.elementText("system"), portletModel.isSystem()));
1785                    portletModel.setActive(
1786                            GetterUtil.getBoolean(
1787                                    portletElement.elementText("active"), portletModel.isActive()));
1788                    portletModel.setInclude(
1789                            GetterUtil.getBoolean(
1790                                    portletElement.elementText("include"),
1791                                    portletModel.isInclude()));
1792    
1793                    if (Validator.isNull(servletContextName)) {
1794                            portletModel.setReady(true);
1795                    }
1796    
1797                    if (!portletModel.isAjaxable() &&
1798                            (portletModel.getRenderWeight() < 1)) {
1799    
1800                            portletModel.setRenderWeight(1);
1801                    }
1802    
1803                    portletModel.getRoleMappers().putAll(roleMappers);
1804                    portletModel.linkRoles();
1805            }
1806    
1807            private Set<String> _readLiferayPortletXML(
1808                            String servletContextName, ServletContext servletContext,
1809                            String xml, Map<String, Portlet> portletsMap)
1810                    throws Exception {
1811    
1812                    Set<String> liferayPortletIds = new HashSet<>();
1813    
1814                    if (xml == null) {
1815                            return liferayPortletIds;
1816                    }
1817    
1818                    Document document = UnsecureSAXReaderUtil.read(xml, true);
1819    
1820                    Element rootElement = document.getRootElement();
1821    
1822                    PortletApp portletApp = getPortletApp(servletContextName);
1823    
1824                    Map<String, String> roleMappers = new HashMap<>();
1825    
1826                    for (Element roleMapperElement : rootElement.elements("role-mapper")) {
1827                            String roleName = roleMapperElement.elementText("role-name");
1828                            String roleLink = roleMapperElement.elementText("role-link");
1829    
1830                            roleMappers.put(roleName, roleLink);
1831                    }
1832    
1833                    Map<String, String> customUserAttributes =
1834                            portletApp.getCustomUserAttributes();
1835    
1836                    for (Element customUserAttributeElement :
1837                                    rootElement.elements("custom-user-attribute")) {
1838    
1839                            String customClass = customUserAttributeElement.elementText(
1840                                    "custom-class");
1841    
1842                            for (Element nameElement :
1843                                            customUserAttributeElement.elements("name")) {
1844    
1845                                    String name = nameElement.getText();
1846    
1847                                    customUserAttributes.put(name, customClass);
1848                            }
1849                    }
1850    
1851                    for (Element portletElement : rootElement.elements("portlet")) {
1852                            _readLiferayPortletXML(
1853                                    servletContextName, servletContext, liferayPortletIds,
1854                                    roleMappers, portletElement, portletsMap);
1855                    }
1856    
1857                    return liferayPortletIds;
1858            }
1859    
1860            private void _readPortletXML(
1861                            String servletContextName, PluginPackage pluginPackage,
1862                            PortletApp portletApp, Element portletElement,
1863                            Map<String, Portlet> portletsMap)
1864                    throws PortletIdException {
1865    
1866                    String portletName = portletElement.elementText("portlet-name");
1867    
1868                    String portletId = portletName;
1869    
1870                    if (Validator.isNotNull(servletContextName)) {
1871                            portletId = portletId.concat(PortletConstants.WAR_SEPARATOR).concat(
1872                                    servletContextName);
1873                    }
1874    
1875                    portletId = PortalUtil.getJsSafePortletId(portletId);
1876    
1877                    if (portletId.length() >
1878                                    PortletInstance.PORTLET_INSTANCE_KEY_MAX_LENGTH) {
1879    
1880                            // LPS-32878
1881    
1882                            throw new PortletIdException(
1883                                    "Portlet ID " + portletId + " has more than " +
1884                                            PortletInstance.PORTLET_INSTANCE_KEY_MAX_LENGTH +
1885                                                    " characters");
1886                    }
1887    
1888                    if (_log.isDebugEnabled()) {
1889                            _log.debug("Reading portlet " + portletId);
1890                    }
1891    
1892                    Portlet portletModel = _portletsMap.get(portletId);
1893    
1894                    if (portletModel == null) {
1895                            portletModel = new PortletImpl(CompanyConstants.SYSTEM, portletId);
1896                    }
1897    
1898                    portletModel.setPluginPackage(pluginPackage);
1899                    portletModel.setPortletApp(portletApp);
1900    
1901                    portletModel.setPortletName(portletName);
1902                    portletModel.setDisplayName(
1903                            GetterUtil.getString(
1904                                    portletElement.elementText("display-name"),
1905                                    portletModel.getDisplayName()));
1906                    portletModel.setPortletClass(
1907                            GetterUtil.getString(portletElement.elementText("portlet-class")));
1908    
1909                    Map<String, String> initParams = new HashMap<>();
1910    
1911                    for (Element initParamElement : portletElement.elements("init-param")) {
1912                            initParams.put(
1913                                    initParamElement.elementText("name"),
1914                                    initParamElement.elementText("value"));
1915                    }
1916    
1917                    portletModel.setInitParams(initParams);
1918    
1919                    Element expirationCacheElement = portletElement.element(
1920                            "expiration-cache");
1921    
1922                    if (expirationCacheElement != null) {
1923                            portletModel.setExpCache(
1924                                    GetterUtil.getInteger(expirationCacheElement.getText()));
1925                    }
1926    
1927                    Map<String, Set<String>> portletModes = new HashMap<>();
1928                    Map<String, Set<String>> windowStates = new HashMap<>();
1929    
1930                    for (Element supportsElement : portletElement.elements("supports")) {
1931                            String mimeType = supportsElement.elementText("mime-type");
1932    
1933                            Set<String> mimeTypePortletModes = new HashSet<>();
1934    
1935                            mimeTypePortletModes.add(
1936                                    StringUtil.toLowerCase(PortletMode.VIEW.toString()));
1937    
1938                            for (Element portletModeElement :
1939                                            supportsElement.elements("portlet-mode")) {
1940    
1941                                    mimeTypePortletModes.add(
1942                                            StringUtil.toLowerCase(portletModeElement.getTextTrim()));
1943                            }
1944    
1945                            portletModes.put(mimeType, mimeTypePortletModes);
1946    
1947                            Set<String> mimeTypeWindowStates = new HashSet<>();
1948    
1949                            mimeTypeWindowStates.add(
1950                                    StringUtil.toLowerCase(WindowState.NORMAL.toString()));
1951    
1952                            List<Element> windowStateElements = supportsElement.elements(
1953                                    "window-state");
1954    
1955                            if (windowStateElements.isEmpty()) {
1956                                    mimeTypeWindowStates.add(
1957                                            StringUtil.toLowerCase(WindowState.MAXIMIZED.toString()));
1958                                    mimeTypeWindowStates.add(
1959                                            StringUtil.toLowerCase(WindowState.MINIMIZED.toString()));
1960                                    mimeTypeWindowStates.add(
1961                                            StringUtil.toLowerCase(
1962                                                    LiferayWindowState.EXCLUSIVE.toString()));
1963                                    mimeTypeWindowStates.add(
1964                                            StringUtil.toLowerCase(
1965                                                    LiferayWindowState.POP_UP.toString()));
1966                            }
1967    
1968                            for (Element windowStateElement : windowStateElements) {
1969                                    mimeTypeWindowStates.add(
1970                                            StringUtil.toLowerCase(windowStateElement.getTextTrim()));
1971                            }
1972    
1973                            windowStates.put(mimeType, mimeTypeWindowStates);
1974                    }
1975    
1976                    portletModel.setPortletModes(portletModes);
1977                    portletModel.setWindowStates(windowStates);
1978    
1979                    Set<String> supportedLocales = new HashSet<>();
1980    
1981                    //supportedLocales.add(
1982                    //        LocaleUtil.toLanguageId(LocaleUtil.getDefault()));
1983    
1984                    for (Element supportedLocaleElement : portletElement.elements(
1985                                    "supported-locale")) {
1986    
1987                            String supportedLocale = supportedLocaleElement.getText();
1988    
1989                            supportedLocales.add(supportedLocale);
1990                    }
1991    
1992                    portletModel.setSupportedLocales(supportedLocales);
1993    
1994                    portletModel.setResourceBundle(
1995                            portletElement.elementText("resource-bundle"));
1996    
1997                    Element portletInfoElement = portletElement.element("portlet-info");
1998    
1999                    String portletInfoTitle = null;
2000                    String portletInfoShortTitle = null;
2001                    String portletInfoKeyWords = null;
2002                    String portletInfoDescription = null;
2003    
2004                    if (portletInfoElement != null) {
2005                            portletInfoTitle = portletInfoElement.elementText("title");
2006                            portletInfoShortTitle = portletInfoElement.elementText(
2007                                    "short-title");
2008                            portletInfoKeyWords = portletInfoElement.elementText("keywords");
2009                    }
2010    
2011                    PortletInfo portletInfo = new PortletInfo(
2012                            portletInfoTitle, portletInfoShortTitle, portletInfoKeyWords,
2013                            portletInfoDescription);
2014    
2015                    portletModel.setPortletInfo(portletInfo);
2016    
2017                    Element portletPreferencesElement = portletElement.element(
2018                            "portlet-preferences");
2019    
2020                    String defaultPreferences = null;
2021                    String preferencesValidator = null;
2022    
2023                    if (portletPreferencesElement != null) {
2024                            Element preferencesValidatorElement =
2025                                    portletPreferencesElement.element("preferences-validator");
2026    
2027                            if (preferencesValidatorElement != null) {
2028                                    preferencesValidator = preferencesValidatorElement.getText();
2029    
2030                                    portletPreferencesElement.remove(preferencesValidatorElement);
2031                            }
2032    
2033                            defaultPreferences = portletPreferencesElement.asXML();
2034                    }
2035    
2036                    portletModel.setDefaultPreferences(defaultPreferences);
2037                    portletModel.setPreferencesValidator(preferencesValidator);
2038    
2039                    if (!portletApp.isWARFile() &&
2040                            Validator.isNotNull(preferencesValidator) &&
2041                            PropsValues.PREFERENCE_VALIDATE_ON_STARTUP) {
2042    
2043                            try {
2044                                    PreferencesValidator preferencesValidatorObj =
2045                                            PortalUtil.getPreferencesValidator(portletModel);
2046    
2047                                    preferencesValidatorObj.validate(
2048                                            PortletPreferencesFactoryUtil.fromDefaultXML(
2049                                                    defaultPreferences));
2050                            }
2051                            catch (Exception e) {
2052                                    if (_log.isWarnEnabled()) {
2053                                            _log.warn(
2054                                                    "Portlet with the name " + portletId +
2055                                                            " does not have valid default preferences");
2056                                    }
2057                            }
2058                    }
2059    
2060                    Set<String> unlinkedRoles = new HashSet<>();
2061    
2062                    for (Element roleElement :
2063                                    portletElement.elements("security-role-ref")) {
2064    
2065                            unlinkedRoles.add(roleElement.elementText("role-name"));
2066                    }
2067    
2068                    portletModel.setUnlinkedRoles(unlinkedRoles);
2069    
2070                    Set<QName> processingEvents = new HashSet<>();
2071    
2072                    for (Element supportedProcessingEventElement :
2073                                    portletElement.elements("supported-processing-event")) {
2074    
2075                            Element qNameElement = supportedProcessingEventElement.element(
2076                                    "qname");
2077                            Element nameElement = supportedProcessingEventElement.element(
2078                                    "name");
2079    
2080                            QName qName = PortletQNameUtil.getQName(
2081                                    qNameElement, nameElement, portletApp.getDefaultNamespace());
2082    
2083                            processingEvents.add(qName);
2084    
2085                            Set<EventDefinition> eventDefinitions =
2086                                    portletApp.getEventDefinitions();
2087    
2088                            for (EventDefinition eventDefinition : eventDefinitions) {
2089                                    Set<QName> qNames = eventDefinition.getQNames();
2090    
2091                                    if (qNames.contains(qName)) {
2092                                            processingEvents.addAll(qNames);
2093                                    }
2094                            }
2095                    }
2096    
2097                    portletModel.setProcessingEvents(processingEvents);
2098    
2099                    Set<QName> publishingEvents = new HashSet<>();
2100    
2101                    for (Element supportedPublishingEventElement :
2102                                    portletElement.elements("supported-publishing-event")) {
2103    
2104                            Element qNameElement = supportedPublishingEventElement.element(
2105                                    "qname");
2106                            Element nameElement = supportedPublishingEventElement.element(
2107                                    "name");
2108    
2109                            QName qName = PortletQNameUtil.getQName(
2110                                    qNameElement, nameElement, portletApp.getDefaultNamespace());
2111    
2112                            publishingEvents.add(qName);
2113                    }
2114    
2115                    portletModel.setPublishingEvents(publishingEvents);
2116    
2117                    Set<PublicRenderParameter> publicRenderParameters = new HashSet<>();
2118    
2119                    for (Element supportedPublicRenderParameter :
2120                                    portletElement.elements("supported-public-render-parameter")) {
2121    
2122                            String identifier = supportedPublicRenderParameter.getTextTrim();
2123    
2124                            PublicRenderParameter publicRenderParameter =
2125                                    portletApp.getPublicRenderParameter(identifier);
2126    
2127                            if (publicRenderParameter == null) {
2128                                    _log.error(
2129                                            "Supported public render parameter references " +
2130                                                    "unknown identifier " + identifier);
2131    
2132                                    continue;
2133                            }
2134    
2135                            publicRenderParameters.add(publicRenderParameter);
2136                    }
2137    
2138                    portletModel.setPublicRenderParameters(publicRenderParameters);
2139    
2140                    portletsMap.put(portletId, portletModel);
2141            }
2142    
2143            private Map<String, Portlet> _readPortletXML(
2144                            String servletContextName, ServletContext servletContext,
2145                            String xml, Set<String> servletURLPatterns,
2146                            PluginPackage pluginPackage)
2147                    throws Exception {
2148    
2149                    Map<String, Portlet> portletsMap = new HashMap<>();
2150    
2151                    if (xml == null) {
2152                            return portletsMap;
2153                    }
2154    
2155                    Document document = UnsecureSAXReaderUtil.read(
2156                            xml, PropsValues.PORTLET_XML_VALIDATE);
2157    
2158                    Element rootElement = document.getRootElement();
2159    
2160                    PortletApp portletApp = getPortletApp(servletContextName);
2161    
2162                    portletApp.addServletURLPatterns(servletURLPatterns);
2163                    portletApp.setServletContext(servletContext);
2164    
2165                    Set<String> userAttributes = portletApp.getUserAttributes();
2166    
2167                    for (Element userAttributeElement :
2168                                    rootElement.elements("user-attribute")) {
2169    
2170                            String name = userAttributeElement.elementText("name");
2171    
2172                            userAttributes.add(name);
2173                    }
2174    
2175                    String defaultNamespace = rootElement.elementText("default-namespace");
2176    
2177                    if (Validator.isNotNull(defaultNamespace)) {
2178                            portletApp.setDefaultNamespace(defaultNamespace);
2179                    }
2180    
2181                    for (Element eventDefinitionElement :
2182                                    rootElement.elements("event-definition")) {
2183    
2184                            Element qNameElement = eventDefinitionElement.element("qname");
2185                            Element nameElement = eventDefinitionElement.element("name");
2186                            String valueType = eventDefinitionElement.elementText("value-type");
2187    
2188                            QName qName = PortletQNameUtil.getQName(
2189                                    qNameElement, nameElement, portletApp.getDefaultNamespace());
2190    
2191                            EventDefinition eventDefinition = new EventDefinitionImpl(
2192                                    qName, valueType, portletApp);
2193    
2194                            List<Element> aliases = eventDefinitionElement.elements("alias");
2195    
2196                            for (Element alias : aliases) {
2197                                    qName = PortletQNameUtil.getQName(
2198                                            alias, null, portletApp.getDefaultNamespace());
2199    
2200                                    eventDefinition.addAliasQName(qName);
2201                            }
2202    
2203                            portletApp.addEventDefinition(eventDefinition);
2204                    }
2205    
2206                    for (Element publicRenderParameterElement :
2207                                    rootElement.elements("public-render-parameter")) {
2208    
2209                            String identifier = publicRenderParameterElement.elementText(
2210                                    "identifier");
2211                            Element qNameElement = publicRenderParameterElement.element(
2212                                    "qname");
2213                            Element nameElement = publicRenderParameterElement.element("name");
2214    
2215                            QName qName = PortletQNameUtil.getQName(
2216                                    qNameElement, nameElement, portletApp.getDefaultNamespace());
2217    
2218                            PublicRenderParameter publicRenderParameter =
2219                                    new PublicRenderParameterImpl(identifier, qName, portletApp);
2220    
2221                            portletApp.addPublicRenderParameter(publicRenderParameter);
2222                    }
2223    
2224                    for (Element containerRuntimeOptionElement :
2225                                    rootElement.elements("container-runtime-option")) {
2226    
2227                            String name = GetterUtil.getString(
2228                                    containerRuntimeOptionElement.elementText("name"));
2229    
2230                            List<String> values = new ArrayList<>();
2231    
2232                            for (Element valueElement :
2233                                            containerRuntimeOptionElement.elements("value")) {
2234    
2235                                    values.add(valueElement.getTextTrim());
2236                            }
2237    
2238                            Map<String, String[]> containerRuntimeOptions =
2239                                    portletApp.getContainerRuntimeOptions();
2240    
2241                            containerRuntimeOptions.put(
2242                                    name, values.toArray(new String[values.size()]));
2243    
2244                            if (name.equals(
2245                                            LiferayPortletConfig.RUNTIME_OPTION_PORTAL_CONTEXT) &&
2246                                    !values.isEmpty() && GetterUtil.getBoolean(values.get(0))) {
2247    
2248                                    portletApp.setWARFile(false);
2249                            }
2250                    }
2251    
2252                    for (Element portletElement : rootElement.elements("portlet")) {
2253                            _readPortletXML(
2254                                    servletContextName, pluginPackage, portletApp, portletElement,
2255                                    portletsMap);
2256                    }
2257    
2258                    for (Element filterElement : rootElement.elements("filter")) {
2259                            String filterName = filterElement.elementText("filter-name");
2260                            String filterClass = filterElement.elementText("filter-class");
2261    
2262                            Set<String> lifecycles = new LinkedHashSet<>();
2263    
2264                            for (Element lifecycleElement :
2265                                            filterElement.elements("lifecycle")) {
2266    
2267                                    lifecycles.add(lifecycleElement.getText());
2268                            }
2269    
2270                            Map<String, String> initParams = new HashMap<>();
2271    
2272                            for (Element initParamElement :
2273                                            filterElement.elements("init-param")) {
2274    
2275                                    initParams.put(
2276                                            initParamElement.elementText("name"),
2277                                            initParamElement.elementText("value"));
2278                            }
2279    
2280                            PortletFilter portletFilter = new PortletFilterImpl(
2281                                    filterName, filterClass, lifecycles, initParams, portletApp);
2282    
2283                            portletApp.addPortletFilter(portletFilter);
2284                    }
2285    
2286                    for (Element filterMappingElement :
2287                                    rootElement.elements("filter-mapping")) {
2288    
2289                            String filterName = filterMappingElement.elementText("filter-name");
2290    
2291                            PortletFilter portletFilter = portletApp.getPortletFilter(
2292                                    filterName);
2293    
2294                            if (portletFilter == null) {
2295                                    _log.error(
2296                                            "Filter mapping references unknown filter name " +
2297                                                    filterName);
2298    
2299                                    continue;
2300                            }
2301    
2302                            for (Element portletNameElement :
2303                                            filterMappingElement.elements("portlet-name")) {
2304    
2305                                    String portletName = portletNameElement.getTextTrim();
2306    
2307                                    List<Portlet> portletModels = _getPortletsByPortletName(
2308                                            portletName, servletContextName, portletsMap);
2309    
2310                                    if (portletModels.isEmpty()) {
2311                                            _log.error(
2312                                                    "Filter mapping with filter name " + filterName +
2313                                                            " references unknown portlet name " + portletName);
2314                                    }
2315    
2316                                    for (Portlet portletModel : portletModels) {
2317                                            portletModel.getPortletFilters().put(
2318                                                    filterName, portletFilter);
2319                                    }
2320                            }
2321                    }
2322    
2323                    for (Element listenerElement : rootElement.elements("listener")) {
2324                            String listenerClass = listenerElement.elementText(
2325                                    "listener-class");
2326    
2327                            PortletURLListener portletURLListener = new PortletURLListenerImpl(
2328                                    listenerClass, portletApp);
2329    
2330                            portletApp.addPortletURLListener(portletURLListener);
2331                    }
2332    
2333                    return portletsMap;
2334            }
2335    
2336            private Set<String> _readWebXML(String xml) throws Exception {
2337                    Set<String> servletURLPatterns = new LinkedHashSet<>();
2338    
2339                    if (xml == null) {
2340                            return servletURLPatterns;
2341                    }
2342    
2343                    Document document = UnsecureSAXReaderUtil.read(xml);
2344    
2345                    Element rootElement = document.getRootElement();
2346    
2347                    for (Element servletMappingElement :
2348                                    rootElement.elements("servlet-mapping")) {
2349    
2350                            String urlPattern = servletMappingElement.elementText(
2351                                    "url-pattern");
2352    
2353                            servletURLPatterns.add(urlPattern);
2354                    }
2355    
2356                    return servletURLPatterns;
2357            }
2358    
2359            private void _setSpriteImages(
2360                            ServletContext servletContext, PortletApp portletApp,
2361                            String resourcePath)
2362                    throws Exception {
2363    
2364                    Set<String> resourcePaths = servletContext.getResourcePaths(
2365                            resourcePath);
2366    
2367                    if ((resourcePaths == null) || resourcePaths.isEmpty()) {
2368                            return;
2369                    }
2370    
2371                    List<URL> imageURLs = new ArrayList<>(resourcePaths.size());
2372    
2373                    for (String curResourcePath : resourcePaths) {
2374                            if (curResourcePath.endsWith(StringPool.SLASH)) {
2375                                    _setSpriteImages(servletContext, portletApp, curResourcePath);
2376                            }
2377                            else if (curResourcePath.endsWith(".png")) {
2378                                    URL imageURL = servletContext.getResource(curResourcePath);
2379    
2380                                    if (imageURL != null) {
2381                                            imageURLs.add(imageURL);
2382                                    }
2383                                    else {
2384                                            _log.error(
2385                                                    "Resource URL for " + curResourcePath + " is null");
2386                                    }
2387                            }
2388                    }
2389    
2390                    String spriteRootDirName = PropsValues.SPRITE_ROOT_DIR;
2391                    String spriteFileName = resourcePath.concat(
2392                            PropsValues.SPRITE_FILE_NAME);
2393                    String spritePropertiesFileName = resourcePath.concat(
2394                            PropsValues.SPRITE_PROPERTIES_FILE_NAME);
2395                    String rootPath = ServletContextUtil.getRootPath(servletContext);
2396    
2397                    Properties spriteProperties = SpriteProcessorUtil.generate(
2398                            servletContext, imageURLs, spriteRootDirName, spriteFileName,
2399                            spritePropertiesFileName, rootPath, 16, 16, 10240);
2400    
2401                    if (spriteProperties == null) {
2402                            return;
2403                    }
2404    
2405                    String contextPath = servletContext.getContextPath();
2406    
2407                    spriteFileName = contextPath.concat(SpriteProcessor.PATH).concat(
2408                            spriteFileName);
2409    
2410                    portletApp.setSpriteImages(spriteFileName, spriteProperties);
2411            }
2412    
2413            private static final Log _log = LogFactoryUtil.getLog(
2414                    PortletLocalServiceImpl.class);
2415    
2416            private static final Map<String, PortletApp> _portletApps =
2417                    new ConcurrentHashMap<>();
2418            private static final Map<String, String> _portletIdsByStrutsPath =
2419                    new ConcurrentHashMap<>();
2420            private static final Map<String, Portlet> _portletsMap =
2421                    new ConcurrentHashMap<>();
2422            private static final Map<Long, Map<String, Portlet>> _portletsMaps =
2423                    new ConcurrentHashMap<>();
2424            private static final Map<ClassLoader, Configuration>
2425                    _propertiesConfigurations = new ConcurrentHashMap<>();
2426    
2427    }