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