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