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