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