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