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.security.permission;
016    
017    import com.liferay.portal.ResourceActionsException;
018    import com.liferay.portal.exception.NoSuchResourceActionException;
019    import com.liferay.portal.kernel.bean.BeanReference;
020    import com.liferay.portal.kernel.language.LanguageUtil;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
024    import com.liferay.portal.kernel.util.CharPool;
025    import com.liferay.portal.kernel.util.ContentTypes;
026    import com.liferay.portal.kernel.util.GetterUtil;
027    import com.liferay.portal.kernel.util.ListUtil;
028    import com.liferay.portal.kernel.util.LocaleUtil;
029    import com.liferay.portal.kernel.util.ResourceBundleUtil;
030    import com.liferay.portal.kernel.util.StringBundler;
031    import com.liferay.portal.kernel.util.StringPool;
032    import com.liferay.portal.kernel.util.StringUtil;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.kernel.xml.Document;
035    import com.liferay.portal.kernel.xml.DocumentType;
036    import com.liferay.portal.kernel.xml.Element;
037    import com.liferay.portal.kernel.xml.UnsecureSAXReaderUtil;
038    import com.liferay.portal.model.Group;
039    import com.liferay.portal.model.Organization;
040    import com.liferay.portal.model.Portlet;
041    import com.liferay.portal.model.PortletConstants;
042    import com.liferay.portal.model.ResourceAction;
043    import com.liferay.portal.model.Role;
044    import com.liferay.portal.model.RoleConstants;
045    import com.liferay.portal.model.User;
046    import com.liferay.portal.service.GroupServiceUtil;
047    import com.liferay.portal.service.PortletLocalService;
048    import com.liferay.portal.service.ResourceActionLocalService;
049    import com.liferay.portal.service.RoleLocalService;
050    import com.liferay.portal.util.PortletKeys;
051    import com.liferay.portal.util.PropsValues;
052    import com.liferay.registry.collections.ServiceTrackerCollections;
053    import com.liferay.registry.collections.ServiceTrackerMap;
054    import com.liferay.util.JS;
055    
056    import java.io.InputStream;
057    
058    import java.util.ArrayList;
059    import java.util.Collections;
060    import java.util.HashMap;
061    import java.util.HashSet;
062    import java.util.Iterator;
063    import java.util.LinkedHashSet;
064    import java.util.List;
065    import java.util.Locale;
066    import java.util.Map;
067    import java.util.ResourceBundle;
068    import java.util.Set;
069    
070    import javax.servlet.http.HttpServletRequest;
071    
072    import org.apache.struts.util.RequestUtils;
073    
074    /**
075     * @author Brian Wing Shun Chan
076     * @author Daeyoung Song
077     * @author Raymond Aug??
078     */
079    @DoPrivileged
080    public class ResourceActionsImpl implements ResourceActions {
081    
082            public ResourceActionsImpl() {
083                    _resourceBundles = ServiceTrackerCollections.openMultiValueMap(
084                            ResourceBundle.class, "language.id");
085            }
086    
087            public void afterPropertiesSet() {
088                    _portletResourceActionsBags = new HashMap<>();
089                    _modelResourceActionsBags = new HashMap<>();
090    
091                    try {
092                            ClassLoader classLoader = getClass().getClassLoader();
093    
094                            for (String config : PropsValues.RESOURCE_ACTIONS_CONFIGS) {
095                                    read(null, classLoader, config);
096                            }
097                    }
098                    catch (Exception e) {
099                            _log.error(e, e);
100                    }
101            }
102    
103            @Override
104            public void checkAction(String name, String actionId)
105                    throws NoSuchResourceActionException {
106    
107                    List<String> resourceActions = getResourceActions(name);
108    
109                    if (!resourceActions.contains(actionId)) {
110                            throw new NoSuchResourceActionException(
111                                    name.concat(StringPool.POUND).concat(actionId));
112                    }
113            }
114    
115            public void destroy() {
116                    _resourceBundles.close();
117            }
118    
119            @Override
120            public String getAction(HttpServletRequest request, String action) {
121                    String key = getActionNamePrefix() + action;
122    
123                    String value = LanguageUtil.get(request, key, null);
124    
125                    if ((value == null) || value.equals(key)) {
126                            value = getResourceBundlesString(request, key);
127                    }
128    
129                    if (value == null) {
130                            value = key;
131                    }
132    
133                    return value;
134            }
135    
136            @Override
137            public String getAction(Locale locale, String action) {
138                    String key = getActionNamePrefix() + action;
139    
140                    String value = LanguageUtil.get(locale, key, null);
141    
142                    if ((value == null) || value.equals(key)) {
143                            value = getResourceBundlesString(locale, key);
144                    }
145    
146                    if (value == null) {
147                            value = key;
148                    }
149    
150                    return value;
151            }
152    
153            @Override
154            public String getActionNamePrefix() {
155                    return _ACTION_NAME_PREFIX;
156            }
157    
158            /**
159             * @deprecated As of 7.0.0
160             */
161            @Deprecated
162            @Override
163            public List<String> getActionsNames(
164                    HttpServletRequest request, List<String> actions) {
165    
166                    Set<String> actionNames = new LinkedHashSet<>();
167    
168                    for (String action : actions) {
169                            actionNames.add(getAction(request, action));
170                    }
171    
172                    return new ArrayList<>(actionNames);
173            }
174    
175            /**
176             * @deprecated As of 7.0.0
177             */
178            @Deprecated
179            @Override
180            public List<String> getActionsNames(
181                    HttpServletRequest request, String name, long actionIds) {
182    
183                    try {
184                            List<ResourceAction> resourceActions =
185                                    resourceActionLocalService.getResourceActions(name);
186    
187                            List<String> actions = new ArrayList<>();
188    
189                            for (ResourceAction resourceAction : resourceActions) {
190                                    long bitwiseValue = resourceAction.getBitwiseValue();
191    
192                                    if ((actionIds & bitwiseValue) == bitwiseValue) {
193                                            actions.add(resourceAction.getActionId());
194                                    }
195                            }
196    
197                            return getActionsNames(request, actions);
198                    }
199                    catch (Exception e) {
200                            _log.error(e, e);
201    
202                            return Collections.emptyList();
203                    }
204            }
205    
206            @Override
207            public String getCompositeModelNameSeparator() {
208                    return _COMPOSITE_MODEL_NAME_SEPARATOR;
209            }
210    
211            @Override
212            public List<String> getModelNames() {
213                    return ListUtil.fromMapKeys(_modelResourceActionsBags);
214            }
215    
216            @Override
217            public List<String> getModelPortletResources(String name) {
218                    ModelResourceActionsBag modelResourceActionsBag =
219                            getModelResourceActionsBag(name);
220    
221                    return new ArrayList<>(modelResourceActionsBag.getResources());
222            }
223    
224            @Override
225            public String getModelResource(HttpServletRequest request, String name) {
226                    String key = getModelResourceNamePrefix() + name;
227    
228                    String value = LanguageUtil.get(request, key, null);
229    
230                    if ((value == null) || value.equals(key)) {
231                            value = getResourceBundlesString(request, key);
232                    }
233    
234                    if (value == null) {
235                            value = key;
236                    }
237    
238                    return value;
239            }
240    
241            @Override
242            public String getModelResource(Locale locale, String name) {
243                    String key = getModelResourceNamePrefix() + name;
244    
245                    String value = LanguageUtil.get(locale, key, null);
246    
247                    if ((value == null) || value.equals(key)) {
248                            value = getResourceBundlesString(locale, key);
249                    }
250    
251                    if (value == null) {
252                            value = key;
253                    }
254    
255                    return value;
256            }
257    
258            @Override
259            public List<String> getModelResourceActions(String name) {
260                    ModelResourceActionsBag modelResourceActionsBag =
261                            getModelResourceActionsBag(name);
262    
263                    return new ArrayList<>(modelResourceActionsBag.getResourceActions());
264            }
265    
266            @Override
267            public List<String> getModelResourceGroupDefaultActions(String name) {
268                    ModelResourceActionsBag modelResourceActionsBag =
269                            getModelResourceActionsBag(name);
270    
271                    return new ArrayList<>(
272                            modelResourceActionsBag.getResourceGroupDefaultActions());
273            }
274    
275            @Override
276            public List<String> getModelResourceGuestDefaultActions(String name) {
277                    ModelResourceActionsBag modelResourceActionsBag =
278                            getModelResourceActionsBag(name);
279    
280                    return new ArrayList<>(
281                            modelResourceActionsBag.getResourceGuestDefaultActions());
282            }
283    
284            @Override
285            public List<String> getModelResourceGuestUnsupportedActions(String name) {
286                    ModelResourceActionsBag modelResourceActionsBag =
287                            getModelResourceActionsBag(name);
288    
289                    return new ArrayList<>(
290                            modelResourceActionsBag.getResourceGuestUnsupportedActions());
291            }
292    
293            @Override
294            public String getModelResourceNamePrefix() {
295                    return _MODEL_RESOURCE_NAME_PREFIX;
296            }
297    
298            @Override
299            public List<String> getModelResourceOwnerDefaultActions(String name) {
300                    ModelResourceActionsBag modelResourceActionsBag =
301                            getModelResourceActionsBag(name);
302    
303                    return new ArrayList<>(
304                            modelResourceActionsBag.getResourceOwnerDefaultActions());
305            }
306    
307            @Override
308            public Double getModelResourceWeight(String name) {
309                    ModelResourceActionsBag modelResourceActionsBag =
310                            getModelResourceActionsBag(name);
311    
312                    Map<String, Double> modelResourceWeights =
313                            modelResourceActionsBag.getResourceWeights();
314    
315                    return modelResourceWeights.get(name);
316            }
317    
318            @Override
319            public String[] getOrganizationModelResources() {
320                    return _organizationModelResources.toArray(
321                            new String[_organizationModelResources.size()]);
322            }
323    
324            @Override
325            public String[] getPortalModelResources() {
326                    return _portalModelResources.toArray(
327                            new String[_portalModelResources.size()]);
328            }
329    
330            @Override
331            public String getPortletBaseResource(String portletName) {
332                    List<String> modelNames = getPortletModelResources(portletName);
333    
334                    for (String modelName : modelNames) {
335                            if (!modelName.contains(".model.")) {
336                                    return modelName;
337                            }
338                    }
339    
340                    return null;
341            }
342    
343            @Override
344            public List<String> getPortletModelResources(String portletName) {
345                    portletName = PortletConstants.getRootPortletId(portletName);
346    
347                    PortletResourceActionsBag portletResourceActionsBag =
348                            getPortletResourceActionsBag(portletName);
349    
350                    Set<String> resources = portletResourceActionsBag.getResources();
351    
352                    if (resources == null) {
353                            return new ArrayList<>();
354                    }
355                    else {
356                            return new ArrayList<>(resources);
357                    }
358            }
359    
360            @Override
361            public List<String> getPortletNames() {
362                    return ListUtil.fromMapKeys(_portletResourceActionsBags);
363            }
364    
365            @Override
366            public List<String> getPortletResourceActions(Portlet portlet) {
367                    Set<String> actions = new LinkedHashSet<>(
368                            getPortletResourceActions(portlet.getPortletId()));
369    
370                    synchronized (this) {
371                            checkPortletActions(portlet, actions);
372                    }
373    
374                    return new ArrayList<>(actions);
375            }
376    
377            @Override
378            public List<String> getPortletResourceActions(String name) {
379                    name = PortletConstants.getRootPortletId(name);
380    
381                    PortletResourceActionsBag portletResourceActionsBag =
382                            getPortletResourceActionsBag(name);
383    
384                    Set<String> actions = portletResourceActionsBag.getResourceActions();
385    
386                    if (!actions.isEmpty()) {
387                            return new ArrayList<>(actions);
388                    }
389    
390                    synchronized (this) {
391                            actions = getPortletMimeTypeActions(name);
392    
393                            if (!name.equals(PortletKeys.PORTAL)) {
394                                    checkPortletActions(name, actions);
395                            }
396    
397                            Set<String> groupDefaultActions =
398                                    portletResourceActionsBag.getResourceGroupDefaultActions();
399    
400                            checkPortletGroupDefaultActions(groupDefaultActions);
401    
402                            Set<String> guestDefaultActions =
403                                    portletResourceActionsBag.getResourceGuestDefaultActions();
404    
405                            checkPortletGuestDefaultActions(guestDefaultActions);
406    
407                            Set<String> layoutManagerActions =
408                                    portletResourceActionsBag.getResourceLayoutManagerActions();
409    
410                            checkPortletLayoutManagerActions(layoutManagerActions);
411                    }
412    
413                    return new ArrayList<>(actions);
414            }
415    
416            @Override
417            public List<String> getPortletResourceGroupDefaultActions(String name) {
418    
419                    // This method should always be called only after
420                    // _getPortletResourceActions has been called at least once to populate
421                    // the default group actions. Check to make sure this is the case.
422                    // However, if it is not, that means the methods
423                    // getPortletResourceGuestDefaultActions and
424                    // getPortletResourceGuestDefaultActions may not work either.
425    
426                    name = PortletConstants.getRootPortletId(name);
427    
428                    PortletResourceActionsBag portletResourceActionsBag =
429                            getPortletResourceActionsBag(name);
430    
431                    return new ArrayList<>(
432                            portletResourceActionsBag.getResourceGroupDefaultActions());
433            }
434    
435            @Override
436            public List<String> getPortletResourceGuestDefaultActions(String name) {
437                    name = PortletConstants.getRootPortletId(name);
438    
439                    PortletResourceActionsBag portletResourceActionsBag =
440                            getPortletResourceActionsBag(name);
441    
442                    return new ArrayList<>(
443                            portletResourceActionsBag.getResourceGuestDefaultActions());
444            }
445    
446            @Override
447            public List<String> getPortletResourceGuestUnsupportedActions(String name) {
448                    name = PortletConstants.getRootPortletId(name);
449    
450                    PortletResourceActionsBag portletResourceActionsBag =
451                            getPortletResourceActionsBag(name);
452    
453                    Set<String> actions =
454                            portletResourceActionsBag.getResourceGuestUnsupportedActions();
455    
456                    if (actions.contains(ActionKeys.CONFIGURATION) &&
457                            actions.contains(ActionKeys.PERMISSIONS)) {
458    
459                            return new ArrayList<>(actions);
460                    }
461    
462                    actions.add(ActionKeys.CONFIGURATION);
463                    actions.add(ActionKeys.PERMISSIONS);
464    
465                    return new ArrayList<>(actions);
466            }
467    
468            @Override
469            public List<String> getPortletResourceLayoutManagerActions(String name) {
470                    name = PortletConstants.getRootPortletId(name);
471    
472                    PortletResourceActionsBag portletResourceActionsBag =
473                            getPortletResourceActionsBag(name);
474    
475                    Set<String> actions =
476                            portletResourceActionsBag.getResourceLayoutManagerActions();
477    
478                    // This check can never return an empty list. If the list is empty, it
479                    // means that the portlet does not have an explicit resource-actions
480                    // configuration file and should therefore be handled as if it has
481                    // defaults of CONFIGURATION, PREFERENCES, and VIEW.
482    
483                    if (actions.isEmpty()) {
484                            actions = new LinkedHashSet<>();
485    
486                            actions.add(ActionKeys.CONFIGURATION);
487                            actions.add(ActionKeys.PREFERENCES);
488                            actions.add(ActionKeys.VIEW);
489                    }
490    
491                    return new ArrayList<>(actions);
492            }
493    
494            @Override
495            public String getPortletRootModelResource(String portletName) {
496                    portletName = PortletConstants.getRootPortletId(portletName);
497    
498                    PortletResourceActionsBag portletResourceActionsBag =
499                            getPortletResourceActionsBag(portletName);
500    
501                    Map<String, String> portletRootModelResource =
502                            portletResourceActionsBag.getPortletRootModelResources();
503    
504                    return portletRootModelResource.get(portletName);
505            }
506    
507            @Override
508            public List<String> getResourceActions(String name) {
509                    if (name.indexOf(CharPool.PERIOD) != -1) {
510                            return getModelResourceActions(name);
511                    }
512                    else {
513                            return getPortletResourceActions(name);
514                    }
515            }
516    
517            @Override
518            public List<String> getResourceActions(
519                    String portletResource, String modelResource) {
520    
521                    List<String> actions = null;
522    
523                    if (Validator.isNull(modelResource)) {
524                            actions = getPortletResourceActions(portletResource);
525                    }
526                    else {
527                            actions = getModelResourceActions(modelResource);
528                    }
529    
530                    return actions;
531            }
532    
533            @Override
534            public List<String> getResourceGroupDefaultActions(String name) {
535                    if (name.contains(StringPool.PERIOD)) {
536                            return getModelResourceGroupDefaultActions(name);
537                    }
538                    else {
539                            return getPortletResourceGroupDefaultActions(name);
540                    }
541            }
542    
543            @Override
544            public List<String> getResourceGuestUnsupportedActions(
545                    String portletResource, String modelResource) {
546    
547                    List<String> actions = null;
548    
549                    if (Validator.isNull(modelResource)) {
550                            actions = getPortletResourceGuestUnsupportedActions(
551                                    portletResource);
552                    }
553                    else {
554                            actions = getModelResourceGuestUnsupportedActions(modelResource);
555                    }
556    
557                    return actions;
558            }
559    
560            /**
561             * @deprecated As of 6.1.0, replaced by {@link #getRoles(long, Group,
562             *             String, int[])}
563             */
564            @Deprecated
565            @Override
566            public List<Role> getRoles(
567                    long companyId, Group group, String modelResource) {
568    
569                    return getRoles(companyId, group, modelResource, null);
570            }
571    
572            @Override
573            public List<Role> getRoles(
574                    long companyId, Group group, String modelResource, int[] roleTypes) {
575    
576                    if (roleTypes == null) {
577                            roleTypes = getRoleTypes(companyId, group, modelResource);
578                    }
579    
580                    return roleLocalService.getRoles(companyId, roleTypes);
581            }
582    
583            @Override
584            public boolean hasModelResourceActions(String name) {
585                    ModelResourceActionsBag modelResourceActionsBag =
586                            getModelResourceActionsBag(name);
587    
588                    Set<String> actions = modelResourceActionsBag.getResourceActions();
589    
590                    if ((actions != null) && !actions.isEmpty()) {
591                            return true;
592                    }
593                    else {
594                            return false;
595                    }
596            }
597    
598            @Override
599            public boolean isOrganizationModelResource(String modelResource) {
600                    if (_organizationModelResources.contains(modelResource)) {
601                            return true;
602                    }
603                    else {
604                            return false;
605                    }
606            }
607    
608            @Override
609            public boolean isPortalModelResource(String modelResource) {
610                    if (_portalModelResources.contains(modelResource)) {
611                            return true;
612                    }
613                    else {
614                            return false;
615                    }
616            }
617    
618            @Override
619            public void read(
620                            String servletContextName, ClassLoader classLoader, String source)
621                    throws Exception {
622    
623                    InputStream inputStream = classLoader.getResourceAsStream(source);
624    
625                    if (inputStream == null) {
626                            if (_log.isInfoEnabled() && !source.endsWith("-ext.xml") &&
627                                    !source.startsWith("META-INF/")) {
628    
629                                    _log.info("Cannot load " + source);
630                            }
631    
632                            return;
633                    }
634    
635                    if (_log.isDebugEnabled()) {
636                            _log.debug("Loading " + source);
637                    }
638    
639                    Document document = UnsecureSAXReaderUtil.read(inputStream, true);
640    
641                    DocumentType documentType = document.getDocumentType();
642    
643                    String publicId = GetterUtil.getString(documentType.getPublicId());
644    
645                    if (publicId.equals(
646                                    "-//Liferay//DTD Resource Action Mapping 6.0.0//EN")) {
647    
648                            if (_log.isWarnEnabled()) {
649                                    _log.warn(
650                                            "Please update " + source + " to use the 6.1.0 format");
651                            }
652                    }
653    
654                    Element rootElement = document.getRootElement();
655    
656                    for (Element resourceElement : rootElement.elements("resource")) {
657                            String file = resourceElement.attributeValue("file").trim();
658    
659                            read(servletContextName, classLoader, file);
660    
661                            String extFile = StringUtil.replace(file, ".xml", "-ext.xml");
662    
663                            read(servletContextName, classLoader, extFile);
664                    }
665    
666                    read(servletContextName, document);
667            }
668    
669            /**
670             * @deprecated As of 7.0.0
671             */
672            @Deprecated
673            @Override
674            public void read(String servletContextName, InputStream inputStream)
675                    throws Exception {
676    
677                    Document document = UnsecureSAXReaderUtil.read(inputStream, true);
678    
679                    read(servletContextName, document);
680            }
681    
682            protected void checkGuestUnsupportedActions(
683                    Set<String> guestUnsupportedActions, Set<String> guestDefaultActions) {
684    
685                    // Guest default actions cannot reference guest unsupported actions
686    
687                    Iterator<String> itr = guestDefaultActions.iterator();
688    
689                    while (itr.hasNext()) {
690                            String actionId = itr.next();
691    
692                            if (guestUnsupportedActions.contains(actionId)) {
693                                    itr.remove();
694                            }
695                    }
696            }
697    
698            protected void checkModelActions(Set<String> actions) {
699                    if (!actions.contains(ActionKeys.PERMISSIONS)) {
700                            actions.add(ActionKeys.PERMISSIONS);
701                    }
702            }
703    
704            protected void checkPortletActions(Portlet portlet, Set<String> actions) {
705                    checkPortletLayoutManagerActions(actions);
706    
707                    if ((portlet != null) &&
708                            (portlet.getControlPanelEntryCategory() != null) &&
709                            !actions.contains(ActionKeys.ACCESS_IN_CONTROL_PANEL)) {
710    
711                            actions.add(ActionKeys.ACCESS_IN_CONTROL_PANEL);
712                    }
713            }
714    
715            protected void checkPortletActions(String name, Set<String> actions) {
716                    Portlet portlet = portletLocalService.getPortletById(name);
717    
718                    checkPortletActions(portlet, actions);
719            }
720    
721            protected void checkPortletGroupDefaultActions(Set<String> actions) {
722                    if (actions.isEmpty()) {
723                            actions.add(ActionKeys.VIEW);
724                    }
725            }
726    
727            protected void checkPortletGuestDefaultActions(Set<String> actions) {
728                    if (actions.isEmpty()) {
729                            actions.add(ActionKeys.VIEW);
730                    }
731            }
732    
733            protected void checkPortletLayoutManagerActions(Set<String> actions) {
734                    if (!actions.contains(ActionKeys.ACCESS_IN_CONTROL_PANEL) &&
735                            !actions.contains(ActionKeys.ADD_TO_PAGE)) {
736    
737                            actions.add(ActionKeys.ADD_TO_PAGE);
738                    }
739    
740                    if (!actions.contains(ActionKeys.CONFIGURATION)) {
741                            actions.add(ActionKeys.CONFIGURATION);
742                    }
743    
744                    if (!actions.contains(ActionKeys.PERMISSIONS)) {
745                            actions.add(ActionKeys.PERMISSIONS);
746                    }
747    
748                    if (!actions.contains(ActionKeys.PREFERENCES)) {
749                            actions.add(ActionKeys.PREFERENCES);
750                    }
751    
752                    if (!actions.contains(ActionKeys.VIEW)) {
753                            actions.add(ActionKeys.VIEW);
754                    }
755            }
756    
757            protected String getCompositeModelName(Element compositeModelNameElement) {
758                    StringBundler sb = new StringBundler();
759    
760                    Iterator<Element> itr = compositeModelNameElement.elementIterator(
761                            "model-name");
762    
763                    while (itr.hasNext()) {
764                            Element modelNameElement = itr.next();
765    
766                            sb.append(modelNameElement.getTextTrim());
767    
768                            if (itr.hasNext()) {
769                                    sb.append(_COMPOSITE_MODEL_NAME_SEPARATOR);
770                            }
771                    }
772    
773                    return sb.toString();
774            }
775    
776            protected ModelResourceActionsBag getModelResourceActionsBag(
777                    String modelName) {
778    
779                    ModelResourceActionsBag modelResourceActionsBag =
780                            _modelResourceActionsBags.get(modelName);
781    
782                    if (modelResourceActionsBag != null) {
783                            return modelResourceActionsBag;
784                    }
785    
786                    synchronized(_modelResourceActionsBags) {
787                            modelResourceActionsBag = _modelResourceActionsBags.get(modelName);
788    
789                            if (modelResourceActionsBag != null) {
790                                    return modelResourceActionsBag;
791                            }
792    
793                            modelResourceActionsBag = new ModelResourceActionsBagImpl();
794    
795                            _modelResourceActionsBags.put(modelName, modelResourceActionsBag);
796                    }
797    
798                    return modelResourceActionsBag;
799            }
800    
801            protected Element getPermissionsChildElement(
802                    Element parentElement, String childElementName) {
803    
804                    Element permissionsElement = parentElement.element("permissions");
805    
806                    if (permissionsElement != null) {
807                            return permissionsElement.element(childElementName);
808                    }
809                    else {
810                            return parentElement.element(childElementName);
811                    }
812            }
813    
814            protected Set<String> getPortletMimeTypeActions(String name) {
815                    Set<String> actions = new LinkedHashSet<>();
816    
817                    Portlet portlet = portletLocalService.getPortletById(name);
818    
819                    if (portlet != null) {
820                            Map<String, Set<String>> portletModes = portlet.getPortletModes();
821    
822                            Set<String> mimeTypePortletModes = portletModes.get(
823                                    ContentTypes.TEXT_HTML);
824    
825                            if (mimeTypePortletModes != null) {
826                                    for (String actionId : mimeTypePortletModes) {
827                                            if (StringUtil.equalsIgnoreCase(actionId, "edit")) {
828                                                    actions.add(ActionKeys.PREFERENCES);
829                                            }
830                                            else if (StringUtil.equalsIgnoreCase(
831                                                                    actionId, "edit_guest")) {
832    
833                                                    actions.add(ActionKeys.GUEST_PREFERENCES);
834                                            }
835                                            else {
836                                                    actions.add(StringUtil.toUpperCase(actionId));
837                                            }
838                                    }
839                            }
840                    }
841                    else {
842                            if (_log.isDebugEnabled()) {
843                                    _log.debug(
844                                            "Unable to obtain resource actions for unknown portlet " +
845                                                    name);
846                            }
847                    }
848    
849                    return actions;
850            }
851    
852            protected PortletResourceActionsBag getPortletResourceActionsBag(
853                    String portletName) {
854    
855                    PortletResourceActionsBag portletResourceActionsBag =
856                            _portletResourceActionsBags.get(portletName);
857    
858                    if (portletResourceActionsBag != null) {
859                            return portletResourceActionsBag;
860                    }
861    
862                    synchronized(_portletResourceActionsBags) {
863                            portletResourceActionsBag = _portletResourceActionsBags.get(
864                                    portletName);
865    
866                            if (portletResourceActionsBag != null) {
867                                    return portletResourceActionsBag;
868                            }
869    
870                            portletResourceActionsBag = new PortletResourceActionsBagImpl();
871    
872                            _portletResourceActionsBags.put(
873                                    portletName, portletResourceActionsBag);
874                    }
875    
876                    return portletResourceActionsBag;
877            }
878    
879            protected String getResourceBundlesString(
880                    HttpServletRequest request, String key) {
881    
882                    Locale locale = RequestUtils.getUserLocale(request, null);
883    
884                    return getResourceBundlesString(locale, key);
885            }
886    
887            protected String getResourceBundlesString(Locale locale, String key) {
888                    if ((locale == null) || (key == null)) {
889                            return null;
890                    }
891    
892                    List<ResourceBundle> resourceBundles = null;
893    
894                    try {
895                            String languageId = LocaleUtil.toLanguageId(locale);
896    
897                            resourceBundles = _resourceBundles.getService(languageId);
898                    }
899                    catch (Exception e) {
900                            _log.error(e, e);
901    
902                            return null;
903                    }
904    
905                    for (ResourceBundle resourceBundle : resourceBundles) {
906                            if (resourceBundle.containsKey(key)) {
907                                    return ResourceBundleUtil.getString(resourceBundle, key);
908                            }
909                    }
910    
911                    return null;
912            }
913    
914            protected int[] getRoleTypes(
915                    long companyId, Group group, String modelResource) {
916    
917                    int[] types = RoleConstants.TYPES_REGULAR_AND_SITE;
918    
919                    if (isPortalModelResource(modelResource)) {
920                            if (modelResource.equals(Organization.class.getName()) ||
921                                    modelResource.equals(User.class.getName())) {
922    
923                                    types = RoleConstants.TYPES_ORGANIZATION_AND_REGULAR;
924                            }
925                            else {
926                                    types = RoleConstants.TYPES_REGULAR;
927                            }
928                    }
929                    else {
930                            if (group != null) {
931                                    if (group.isLayout()) {
932                                            try {
933                                                    group = GroupServiceUtil.getGroup(
934                                                            group.getParentGroupId());
935                                            }
936                                            catch (Exception e) {
937                                            }
938                                    }
939    
940                                    if (group.isOrganization()) {
941                                            types =
942                                                    RoleConstants.TYPES_ORGANIZATION_AND_REGULAR_AND_SITE;
943                                    }
944                                    else if (group.isUser()) {
945                                            types = RoleConstants.TYPES_REGULAR;
946                                    }
947                            }
948                    }
949    
950                    return types;
951            }
952    
953            protected void read(String servletContextName, Document document)
954                    throws Exception {
955    
956                    Element rootElement = document.getRootElement();
957    
958                    if (PropsValues.RESOURCE_ACTIONS_READ_PORTLET_RESOURCES) {
959                            for (Element portletResourceElement :
960                                            rootElement.elements("portlet-resource")) {
961    
962                                    readPortletResource(servletContextName, portletResourceElement);
963                            }
964                    }
965    
966                    for (Element modelResourceElement :
967                                    rootElement.elements("model-resource")) {
968    
969                            readModelResource(servletContextName, modelResourceElement);
970                    }
971            }
972    
973            protected List<String> readActionKeys(Element parentElement) {
974                    List<String> actions = new ArrayList<>();
975    
976                    for (Element actionKeyElement : parentElement.elements("action-key")) {
977                            String actionKey = actionKeyElement.getTextTrim();
978    
979                            if (Validator.isNull(actionKey)) {
980                                    continue;
981                            }
982    
983                            actions.add(actionKey);
984                    }
985    
986                    return actions;
987            }
988    
989            protected void readGroupDefaultActions(
990                    Element parentElement, Set<String> groupDefaultActions) {
991    
992                    Element groupDefaultsElement = getPermissionsChildElement(
993                            parentElement, "site-member-defaults");
994    
995                    if (groupDefaultsElement == null) {
996                            groupDefaultsElement = getPermissionsChildElement(
997                                    parentElement, "community-defaults");
998    
999                            if (_log.isWarnEnabled() && (groupDefaultsElement != null)) {
1000                                    _log.warn(
1001                                            "The community-defaults element is deprecated. Use the " +
1002                                                    "site-member-defaults element instead.");
1003                            }
1004                    }
1005    
1006                    groupDefaultActions.addAll(readActionKeys(groupDefaultsElement));
1007            }
1008    
1009            protected void readGuestDefaultActions(
1010                    Element parentElement, Set<String> guestDefaultActions) {
1011    
1012                    Element guestDefaultsElement = getPermissionsChildElement(
1013                            parentElement, "guest-defaults");
1014    
1015                    guestDefaultActions.addAll(readActionKeys(guestDefaultsElement));
1016            }
1017    
1018            protected void readGuestUnsupportedActions(
1019                    Element parentElement, Set<String> guestUnsupportedActions,
1020                    Set<String> guestDefaultActions) {
1021    
1022                    Element guestUnsupportedElement = getPermissionsChildElement(
1023                            parentElement, "guest-unsupported");
1024    
1025                    guestUnsupportedActions.addAll(readActionKeys(guestUnsupportedElement));
1026    
1027                    checkGuestUnsupportedActions(
1028                            guestUnsupportedActions, guestDefaultActions);
1029            }
1030    
1031            protected void readLayoutManagerActions(
1032                    Element parentElement, Set<String> layoutManagerActions,
1033                    Set<String> supportsActions) {
1034    
1035                    Element layoutManagerElement = getPermissionsChildElement(
1036                            parentElement, "layout-manager");
1037    
1038                    if (layoutManagerElement != null) {
1039                            layoutManagerActions.addAll(readActionKeys(layoutManagerElement));
1040                    }
1041                    else {
1042                            layoutManagerActions.addAll(supportsActions);
1043                    }
1044            }
1045    
1046            protected void readModelResource(
1047                            String servletContextName, Element modelResourceElement)
1048                    throws Exception {
1049    
1050                    String name = modelResourceElement.elementTextTrim("model-name");
1051    
1052                    if (Validator.isNull(name)) {
1053                            name = getCompositeModelName(
1054                                    modelResourceElement.element("composite-model-name"));
1055                    }
1056    
1057                    if (GetterUtil.getBoolean(
1058                                    modelResourceElement.attributeValue("organization"))) {
1059    
1060                            _organizationModelResources.add(name);
1061                    }
1062    
1063                    if (GetterUtil.getBoolean(
1064                                    modelResourceElement.attributeValue("portal"))) {
1065    
1066                            _portalModelResources.add(name);
1067                    }
1068    
1069                    ModelResourceActionsBag modelResourceActionsBag =
1070                            getModelResourceActionsBag(name);
1071    
1072                    Element portletRefElement = modelResourceElement.element("portlet-ref");
1073    
1074                    for (Element portletNameElement :
1075                                    portletRefElement.elements("portlet-name")) {
1076    
1077                            String portletName = portletNameElement.getTextTrim();
1078    
1079                            if (servletContextName != null) {
1080                                    portletName = portletName.concat(
1081                                            PortletConstants.WAR_SEPARATOR).concat(servletContextName);
1082                            }
1083    
1084                            portletName = JS.getSafeName(portletName);
1085    
1086                            // Reference for a portlet to child models
1087    
1088                            PortletResourceActionsBag portletResourceActionsBag =
1089                                    getPortletResourceActionsBag(portletName);
1090    
1091                            Set<String> modelResources =
1092                                    portletResourceActionsBag.getResources();
1093    
1094                            modelResources.add(name);
1095    
1096                            // Reference for a model to parent portlets
1097    
1098                            Set<String> portletResources =
1099                                    modelResourceActionsBag.getResources();
1100    
1101                            portletResources.add(portletName);
1102    
1103                            // Reference for a model to root portlets
1104    
1105                            boolean root = GetterUtil.getBoolean(
1106                                    modelResourceElement.elementText("root"));
1107    
1108                            if (root) {
1109                                    Map<String, String> portletRootModelResource =
1110                                            portletResourceActionsBag.getPortletRootModelResources();
1111    
1112                                    portletRootModelResource.put(portletName, name);
1113                            }
1114                    }
1115    
1116                    double weight = GetterUtil.getDouble(
1117                            modelResourceElement.elementTextTrim("weight"), 100);
1118    
1119                    Map<String, Double> modelResourceWeights =
1120                            modelResourceActionsBag.getResourceWeights();
1121    
1122                    modelResourceWeights.put(name, weight);
1123    
1124                    Set<String> modelResourceActions =
1125                            modelResourceActionsBag.getResourceActions();
1126    
1127                    readSupportsActions(modelResourceElement, modelResourceActions);
1128    
1129                    checkModelActions(modelResourceActions);
1130    
1131                    if (modelResourceActions.size() > 64) {
1132                            throw new ResourceActionsException(
1133                                    "There are more than 64 actions for resource " + name);
1134                    }
1135    
1136                    Set<String> modelResourceGroupDefaultActions =
1137                            modelResourceActionsBag.getResourceGroupDefaultActions();
1138    
1139                    readGroupDefaultActions(
1140                            modelResourceElement, modelResourceGroupDefaultActions);
1141    
1142                    Set<String> modelResourceGuestDefaultActions =
1143                            modelResourceActionsBag.getResourceGuestDefaultActions();
1144    
1145                    readGuestDefaultActions(
1146                            modelResourceElement, modelResourceGuestDefaultActions);
1147    
1148                    Set<String> modelResourceGuestUnsupportedActions =
1149                            modelResourceActionsBag.getResourceGuestUnsupportedActions();
1150    
1151                    readGuestUnsupportedActions(
1152                            modelResourceElement, modelResourceGuestUnsupportedActions,
1153                            modelResourceGuestDefaultActions);
1154    
1155                    Set<String> modelResourceOwnerDefaultActions =
1156                            modelResourceActionsBag.getResourceOwnerDefaultActions();
1157    
1158                    readOwnerDefaultActions(
1159                            modelResourceElement, modelResourceOwnerDefaultActions);
1160            }
1161    
1162            protected void readOwnerDefaultActions(
1163                    Element parentElement, Set<String> ownerDefaultActions) {
1164    
1165                    Element ownerDefaultsElement = getPermissionsChildElement(
1166                            parentElement, "owner-defaults");
1167    
1168                    if (ownerDefaultsElement == null) {
1169                            return;
1170                    }
1171    
1172                    ownerDefaultActions.addAll(readActionKeys(ownerDefaultsElement));
1173            }
1174    
1175            protected void readPortletResource(
1176                            String servletContextName, Element portletResourceElement)
1177                    throws Exception {
1178    
1179                    String name = portletResourceElement.elementTextTrim("portlet-name");
1180    
1181                    if (servletContextName != null) {
1182                            name = name.concat(PortletConstants.WAR_SEPARATOR).concat(
1183                                    servletContextName);
1184                    }
1185    
1186                    name = JS.getSafeName(name);
1187    
1188                    PortletResourceActionsBag portletResourceActionsBag =
1189                            getPortletResourceActionsBag(name);
1190    
1191                    Set<String> portletResourceActions =
1192                            portletResourceActionsBag.getResourceActions();
1193    
1194                    readSupportsActions(portletResourceElement, portletResourceActions);
1195    
1196                    portletResourceActions.addAll(getPortletMimeTypeActions(name));
1197    
1198                    if (!name.equals(PortletKeys.PORTAL)) {
1199                            checkPortletActions(name, portletResourceActions);
1200                    }
1201    
1202                    if (portletResourceActions.size() > 64) {
1203                            throw new ResourceActionsException(
1204                                    "There are more than 64 actions for resource " + name);
1205                    }
1206    
1207                    Set<String> portletResourceGroupDefaultActions =
1208                            portletResourceActionsBag.getResourceGroupDefaultActions();
1209    
1210                    readGroupDefaultActions(
1211                            portletResourceElement, portletResourceGroupDefaultActions);
1212    
1213                    Set<String> portletResourceGuestDefaultActions =
1214                            portletResourceActionsBag.getResourceGuestDefaultActions();
1215    
1216                    readGuestDefaultActions(
1217                            portletResourceElement, portletResourceGuestDefaultActions);
1218    
1219                    Set<String> portletResourceGuestUnsupportedActions =
1220                            portletResourceActionsBag.getResourceGuestUnsupportedActions();
1221    
1222                    readGuestUnsupportedActions(
1223                            portletResourceElement, portletResourceGuestUnsupportedActions,
1224                            portletResourceGuestDefaultActions);
1225    
1226                    Set<String> portletResourceLayoutManagerActions =
1227                            portletResourceActionsBag.getResourceLayoutManagerActions();
1228    
1229                    readLayoutManagerActions(
1230                            portletResourceElement, portletResourceLayoutManagerActions,
1231                            portletResourceActions);
1232            }
1233    
1234            protected Set<String> readSupportsActions(
1235                    Element parentElement, Set<String> supportsActions) {
1236    
1237                    Element supportsElement = getPermissionsChildElement(
1238                            parentElement, "supports");
1239    
1240                    supportsActions.addAll(readActionKeys(supportsElement));
1241    
1242                    return supportsActions;
1243            }
1244    
1245            @BeanReference(type = PortletLocalService.class)
1246            protected PortletLocalService portletLocalService;
1247    
1248            @BeanReference(type = ResourceActionLocalService.class)
1249            protected ResourceActionLocalService resourceActionLocalService;
1250    
1251            @BeanReference(type = RoleLocalService.class)
1252            protected RoleLocalService roleLocalService;
1253    
1254            private static final String _ACTION_NAME_PREFIX = "action.";
1255    
1256            private static final String _COMPOSITE_MODEL_NAME_SEPARATOR =
1257                    StringPool.DASH;
1258    
1259            private static final String _MODEL_RESOURCE_NAME_PREFIX = "model.resource.";
1260    
1261            private static final Log _log = LogFactoryUtil.getLog(
1262                    ResourceActionsImpl.class);
1263    
1264            private Map<String, ModelResourceActionsBag> _modelResourceActionsBags;
1265            private final Set<String> _organizationModelResources = new HashSet<>();
1266            private final Set<String> _portalModelResources = new HashSet<>();
1267            private Map<String, PortletResourceActionsBag> _portletResourceActionsBags;
1268            private final ServiceTrackerMap<String, List<ResourceBundle>>
1269                    _resourceBundles;
1270    
1271    }