001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.portal.NoSuchResourcePermissionException;
018    import com.liferay.portal.kernel.concurrent.LockRegistry;
019    import com.liferay.portal.kernel.dao.db.DB;
020    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
021    import com.liferay.portal.kernel.exception.PortalException;
022    import com.liferay.portal.kernel.exception.SystemException;
023    import com.liferay.portal.kernel.search.SearchEngineUtil;
024    import com.liferay.portal.kernel.util.StringBundler;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.StringUtil;
027    import com.liferay.portal.model.Resource;
028    import com.liferay.portal.model.ResourceAction;
029    import com.liferay.portal.model.ResourceConstants;
030    import com.liferay.portal.model.ResourcePermission;
031    import com.liferay.portal.model.ResourcePermissionConstants;
032    import com.liferay.portal.model.Role;
033    import com.liferay.portal.model.RoleConstants;
034    import com.liferay.portal.security.permission.PermissionCacheUtil;
035    import com.liferay.portal.security.permission.PermissionThreadLocal;
036    import com.liferay.portal.security.permission.ResourceActionsUtil;
037    import com.liferay.portal.service.base.ResourcePermissionLocalServiceBaseImpl;
038    import com.liferay.portal.util.PortalUtil;
039    import com.liferay.portal.util.PropsValues;
040    import com.liferay.portal.util.ResourcePermissionsThreadLocal;
041    
042    import java.util.ArrayList;
043    import java.util.Collection;
044    import java.util.Collections;
045    import java.util.HashMap;
046    import java.util.HashSet;
047    import java.util.List;
048    import java.util.Map;
049    import java.util.Set;
050    import java.util.concurrent.locks.Lock;
051    
052    /**
053     * Manages the creation and upkeep of resource permissions, and provides methods
054     * for granting, revoking, and checking permissions.
055     *
056     * <p>
057     * Before attempting to read any of the documentation for this class, first read
058     * {@link com.liferay.portal.model.impl.ResourcePermissionImpl} for an
059     * explanation of scoping.
060     * </p>
061     *
062     * @author Brian Wing Shun Chan
063     * @author Raymond Augé
064     * @author Connor McKay
065     */
066    public class ResourcePermissionLocalServiceImpl
067            extends ResourcePermissionLocalServiceBaseImpl {
068    
069            /**
070             * @see com.liferay.portal.verify.VerifyPermission#fixOrganizationRolePermissions
071             */
072            public static final String[] EMPTY_ACTION_IDS = {null};
073    
074            /**
075             * Grants the role permission at the scope to perform the action on
076             * resources of the type. Existing actions are retained.
077             *
078             * <p>
079             * This method cannot be used to grant individual scope permissions, but is
080             * only intended for adding permissions at the company, group, and
081             * group-template scopes. For example, this method could be used to grant a
082             * company scope permission to edit message board posts.
083             * </p>
084             *
085             * <p>
086             * If a company scope permission is granted to resources that the role
087             * already had group scope permissions to, the group scope permissions are
088             * deleted. Likewise, if a group scope permission is granted to resources
089             * that the role already had company scope permissions to, the company scope
090             * permissions are deleted. Be aware that this latter behavior can result in
091             * an overall reduction in permissions for the role.
092             * </p>
093             *
094             * <p>
095             * Depending on the scope, the value of <code>primKey</code> will have
096             * different meanings. For more information, see {@link
097             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
098             * </p>
099             *
100             * @param  companyId the primary key of the company
101             * @param  name the resource's name, which can be either a class name or a
102             *         portlet ID
103             * @param  scope the scope. This method only supports company, group, and
104             *         group-template scope.
105             * @param  primKey the primary key
106             * @param  roleId the primary key of the role
107             * @param  actionId the action ID
108             * @throws PortalException if scope was set to individual scope or if a role
109             *         with the primary key or a resource action with the name and
110             *         action ID could not be found
111             * @throws SystemException if a system exception occurred
112             */
113            public void addResourcePermission(
114                            long companyId, String name, int scope, String primKey, long roleId,
115                            String actionId)
116                    throws PortalException, SystemException {
117    
118                    if (scope == ResourceConstants.SCOPE_COMPANY) {
119    
120                            // Remove group permission
121    
122                            removeResourcePermissions(
123                                    companyId, name, ResourceConstants.SCOPE_GROUP, roleId,
124                                    actionId);
125                    }
126                    else if (scope == ResourceConstants.SCOPE_GROUP) {
127    
128                            // Remove company permission
129    
130                            removeResourcePermissions(
131                                    companyId, name, ResourceConstants.SCOPE_COMPANY, roleId,
132                                    actionId);
133                    }
134                    else if (scope == ResourceConstants.SCOPE_INDIVIDUAL) {
135                            throw new NoSuchResourcePermissionException();
136                    }
137    
138                    updateResourcePermission(
139                            companyId, name, scope, primKey, roleId, 0, new String[] {actionId},
140                            ResourcePermissionConstants.OPERATOR_ADD);
141    
142                    PermissionCacheUtil.clearCache();
143            }
144    
145            /**
146             * Grants the role permissions at the scope to perform the actions on all
147             * resources of the type. Existing actions are retained.
148             *
149             * <p>
150             * This method should only be used to add default permissions to existing
151             * resources en masse during upgrades or while verifying permissions. For
152             * example, this method could be used to grant site members individual scope
153             * permissions to view all blog posts.
154             * </p>
155             *
156             * @param  resourceName the resource's name, which can be either a class
157             *         name or a portlet ID
158             * @param  roleName the role's name
159             * @param  scope the scope
160             * @param  resourceActionBitwiseValue the bitwise IDs of the actions
161             * @throws SystemException if a system exception occurred
162             */
163            public void addResourcePermissions(
164                            String resourceName, String roleName, int scope,
165                            long resourceActionBitwiseValue)
166                    throws SystemException {
167    
168                    List<Role> roles = rolePersistence.findByName(roleName);
169    
170                    for (Role role : roles) {
171                            List<String> primKeys = resourcePermissionFinder.findByC_N_S(
172                                    role.getCompanyId(), resourceName, scope);
173    
174                            for (String primKey : primKeys) {
175                                    List<ResourcePermission> resourcePermissions =
176                                            resourcePermissionPersistence.findByC_N_S_P_R(
177                                                    role.getCompanyId(), resourceName, scope, primKey,
178                                                    role.getRoleId());
179    
180                                    ResourcePermission resourcePermission = null;
181    
182                                    if (resourcePermissions.isEmpty()) {
183                                            long resourcePermissionId = counterLocalService.increment(
184                                                    ResourcePermission.class.getName());
185    
186                                            resourcePermission = resourcePermissionPersistence.create(
187                                                    resourcePermissionId);
188    
189                                            resourcePermission.setCompanyId(role.getCompanyId());
190                                            resourcePermission.setName(resourceName);
191                                            resourcePermission.setScope(scope);
192                                            resourcePermission.setPrimKey(primKey);
193                                            resourcePermission.setRoleId(role.getRoleId());
194                                    }
195                                    else {
196                                            resourcePermission = resourcePermissions.get(0);
197                                    }
198    
199                                    long actionIdsLong = resourcePermission.getActionIds();
200    
201                                    actionIdsLong |= resourceActionBitwiseValue;
202    
203                                    resourcePermission.setActionIds(actionIdsLong);
204    
205                                    resourcePermissionPersistence.update(resourcePermission);
206                            }
207                    }
208            }
209    
210            /**
211             * Deletes all resource permissions at the scope to resources of the type.
212             * This method should not be confused with any of the
213             * <code>removeResourcePermission</code> methods, as its purpose is very
214             * different. This method should only be used for deleting resource
215             * permissions that refer to a resource when that resource is deleted. For
216             * example this method could be used to delete all individual scope
217             * permissions to a blog post when it is deleted.
218             *
219             * <p>
220             * Depending on the scope, the value of <code>primKey</code> will have
221             * different meanings. For more information, see {@link
222             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
223             * </p>
224             *
225             * @param  companyId the primary key of the company
226             * @param  name the resource's name, which can be either a class name or a
227             *         portlet ID
228             * @param  scope the scope
229             * @param  primKey the primary key
230             * @throws PortalException if a portal exception occurred
231             * @throws SystemException if a system exception occurred
232             */
233            public void deleteResourcePermissions(
234                            long companyId, String name, int scope, long primKey)
235                    throws PortalException, SystemException {
236    
237                    deleteResourcePermissions(
238                            companyId, name, scope, String.valueOf(primKey));
239            }
240    
241            /**
242             * Deletes all resource permissions at the scope to resources of the type.
243             * This method should not be confused with any of the
244             * <code>removeResourcePermission</code> methods, as its purpose is very
245             * different. This method should only be used for deleting resource
246             * permissions that refer to a resource when that resource is deleted. For
247             * example this method could be used to delete all individual scope
248             * permissions to a blog post when it is deleted.
249             *
250             * <p>
251             * Depending on the scope, the value of <code>primKey</code> will have
252             * different meanings. For more information, see {@link
253             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
254             * </p>
255             *
256             * @param  companyId the primary key of the company
257             * @param  name the resource's name, which can be either a class name or a
258             *         portlet ID
259             * @param  scope the scope
260             * @param  primKey the primary key
261             * @throws PortalException if a portal exception occurred
262             * @throws SystemException if a system exception occurred
263             */
264            public void deleteResourcePermissions(
265                            long companyId, String name, int scope, String primKey)
266                    throws PortalException, SystemException {
267    
268                    List<ResourcePermission> resourcePermissions =
269                            resourcePermissionPersistence.findByC_N_S_P(
270                                    companyId, name, scope, primKey);
271    
272                    for (ResourcePermission resourcePermission : resourcePermissions) {
273                            deleteResourcePermission(
274                                    resourcePermission.getResourcePermissionId());
275                    }
276            }
277    
278            /**
279             * Returns the intersection of action IDs the role has permission at the
280             * scope to perform on resources of the type.
281             *
282             * @param  companyId he primary key of the company
283             * @param  name the resource's name, which can be either a class name or a
284             *         portlet ID
285             * @param  scope the scope
286             * @param  primKey the primary key
287             * @param  roleId the primary key of the role
288             * @param  actionIds the action IDs
289             * @return the intersection of action IDs the role has permission at the
290             *         scope to perform on resources of the type
291             * @throws PortalException if a resouce action could not be found for any
292             *         one of the actions on the resource
293             * @throws SystemException if a system exception occurred
294             */
295            public List<String> getAvailableResourcePermissionActionIds(
296                            long companyId, String name, int scope, String primKey, long roleId,
297                            Collection<String> actionIds)
298                    throws PortalException, SystemException {
299    
300                    List<ResourcePermission> resourcePermissions =
301                            resourcePermissionPersistence.findByC_N_S_P_R(
302                                    companyId, name, scope, primKey, roleId);
303    
304                    if (resourcePermissions.isEmpty()) {
305                            return Collections.emptyList();
306                    }
307    
308                    ResourcePermission resourcePermission = resourcePermissions.get(0);
309    
310                    List<String> availableActionIds = new ArrayList<String>(
311                            actionIds.size());
312    
313                    for (String actionId : actionIds) {
314                            ResourceAction resourceAction =
315                                    resourceActionLocalService.getResourceAction(name, actionId);
316    
317                            if (hasActionId(resourcePermission, resourceAction)) {
318                                    availableActionIds.add(actionId);
319                            }
320                    }
321    
322                    return availableActionIds;
323            }
324    
325            public Map<Long, Set<String>> getAvailableResourcePermissionActionIds(
326                            long companyId, String name, int scope, String primKey,
327                            long[] roleIds, Collection<String> actionIds)
328                    throws PortalException, SystemException {
329    
330                    List<ResourcePermission> resourcePermissions =
331                            resourcePermissionPersistence.findByC_N_S_P_R(
332                                    companyId, name, scope, primKey, roleIds);
333    
334                    if (resourcePermissions.isEmpty()) {
335                            return Collections.emptyMap();
336                    }
337    
338                    Map<Long, Set<String>> roleIdsToActionIds =
339                            new HashMap<Long, Set<String>>();
340    
341                    for (ResourcePermission resourcePermission : resourcePermissions) {
342                            long roleId = resourcePermission.getRoleId();
343    
344                            Set<String> availableActionIds = roleIdsToActionIds.get(roleId);
345    
346                            if (availableActionIds != null) {
347                                    continue;
348                            }
349    
350                            availableActionIds = new HashSet<String>();
351    
352                            roleIdsToActionIds.put(roleId, availableActionIds);
353    
354                            for (String actionId : actionIds) {
355                                    ResourceAction resourceAction =
356                                            resourceActionLocalService.getResourceAction(
357                                                    name, actionId);
358    
359                                    if (hasActionId(resourcePermission, resourceAction)) {
360                                            availableActionIds.add(actionId);
361                                    }
362                            }
363                    }
364    
365                    return roleIdsToActionIds;
366            }
367    
368            /**
369             * Returns the resource permission for the role at the scope to perform the
370             * actions on resources of the type.
371             *
372             * @param  companyId the primary key of the company
373             * @param  name the resource's name, which can be either a class name or a
374             *         portlet ID
375             * @param  scope the scope
376             * @param  primKey the primary key
377             * @param  roleId the primary key of the role
378             * @return the resource permission for the role at the scope to perform the
379             *         actions on resources of the type
380             * @throws PortalException if no matching resources could be found
381             * @throws SystemException if a system exception occurred
382             */
383            public ResourcePermission getResourcePermission(
384                            long companyId, String name, int scope, String primKey, long roleId)
385                    throws PortalException, SystemException {
386    
387                    List<ResourcePermission> resourcePermissions =
388                            resourcePermissionPersistence.findByC_N_S_P_R(
389                                    companyId, name, scope, primKey, roleId);
390    
391                    if (!resourcePermissions.isEmpty()) {
392                            return resourcePermissions.get(0);
393                    }
394    
395                    StringBundler sb = new StringBundler(11);
396    
397                    sb.append("No ResourcePermission exists with the key {companyId=");
398                    sb.append(companyId);
399                    sb.append(", name=");
400                    sb.append(name);
401                    sb.append(", scope=");
402                    sb.append(scope);
403                    sb.append(", primKey=");
404                    sb.append(primKey);
405                    sb.append(", roleId=");
406                    sb.append(roleId);
407                    sb.append("}");
408    
409                    throw new NoSuchResourcePermissionException(sb.toString());
410            }
411    
412            /**
413             * Returns all the resource permissions at the scope of the type.
414             *
415             * @param  companyId the primary key of the company
416             * @param  name the resource's name, which can be either a class name or a
417             *         portlet ID
418             * @param  scope the scope
419             * @param  primKey the primary key
420             * @return the resource permissions at the scope of the type
421             * @throws SystemException if a system exception occurred
422             */
423            public List<ResourcePermission> getResourcePermissions(
424                            long companyId, String name, int scope, String primKey)
425                    throws SystemException {
426    
427                    return resourcePermissionPersistence.findByC_N_S_P(
428                            companyId, name, scope, primKey);
429            }
430    
431            /**
432             * Returns the number of resource permissions at the scope of the type.
433             *
434             * @param  companyId the primary key of the company
435             * @param  name the resource's name, which can be either a class name or a
436             *         portlet ID
437             * @param  scope the scope
438             * @param  primKey the primary key
439             * @return the number of resource permissions at the scope of the type
440             * @throws SystemException if a system exception occurred
441             */
442            public int getResourcePermissionsCount(
443                            long companyId, String name, int scope, String primKey)
444                    throws SystemException {
445    
446                    return resourcePermissionPersistence.countByC_N_S_P(
447                            companyId, name, scope, primKey);
448            }
449    
450            /**
451             * Returns the resource permissions that apply to the resource.
452             *
453             * @param  companyId the primary key of the resource's company
454             * @param  groupId the primary key of the resource's group
455             * @param  name the resource's name, which can be either a class name or a
456             *         portlet ID
457             * @param  primKey the primary key of the resource
458             * @return the resource permissions associated with the resource
459             * @throws SystemException if a system exception occurred
460             */
461            public List<ResourcePermission> getResourceResourcePermissions(
462                            long companyId, long groupId, String name, String primKey)
463                    throws SystemException {
464    
465                    return resourcePermissionFinder.findByResource(
466                            companyId, groupId, name, primKey);
467            }
468    
469            /**
470             * Returns all the resource permissions for the role.
471             *
472             * @param  roleId the primary key of the role
473             * @return the resource permissions for the role
474             * @throws SystemException if a system exception occurred
475             */
476            public List<ResourcePermission> getRoleResourcePermissions(long roleId)
477                    throws SystemException {
478    
479                    return resourcePermissionPersistence.findByRoleId(roleId);
480            }
481    
482            /**
483             * Returns a range of all the resource permissions for the role at the
484             * scopes.
485             *
486             * <p>
487             * Useful when paginating results. Returns a maximum of <code>end -
488             * start</code> instances. <code>start</code> and <code>end</code> are not
489             * primary keys, they are indexes in the result set. Thus, <code>0</code>
490             * refers to the first result in the set. Setting both <code>start</code>
491             * and <code>end</code> to {@link
492             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
493             * result set.
494             * </p>
495             *
496             * @param  roleId the primary key of the role
497             * @param  scopes the scopes
498             * @param  start the lower bound of the range of results
499             * @param  end the upper bound of the range of results (not inclusive)
500             * @return the range of resource permissions for the role at the scopes
501             * @throws SystemException if a system exception occurred
502             */
503            public List<ResourcePermission> getRoleResourcePermissions(
504                            long roleId, int[] scopes, int start, int end)
505                    throws SystemException {
506    
507                    return resourcePermissionFinder.findByR_S(roleId, scopes, start, end);
508            }
509    
510            /**
511             * Returns all the resource permissions where scope = any &#63;.
512             *
513             * <p>
514             * Useful when paginating results. Returns a maximum of <code>end -
515             * start</code> instances. <code>start</code> and <code>end</code> are not
516             * primary keys, they are indexes in the result set. Thus, <code>0</code>
517             * refers to the first result in the set. Setting both <code>start</code>
518             * and <code>end</code> to {@link
519             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
520             * result set.
521             * </p>
522             *
523             * @param  scopes the scopes
524             * @return the resource permissions where scope = any &#63;
525             * @throws SystemException if a system exception occurred
526             */
527            public List<ResourcePermission> getScopeResourcePermissions(int[] scopes)
528                    throws SystemException {
529    
530                    return resourcePermissionPersistence.findByScope(scopes);
531            }
532    
533            /**
534             * Returns <code>true</code> if the resource permission grants permission to
535             * perform the resource action. Note that this method does not ensure that
536             * the resource permission refers to the same type of resource as the
537             * resource action.
538             *
539             * @param  resourcePermission the resource permission
540             * @param  resourceAction the resource action
541             * @return <code>true</code> if the resource permission grants permission to
542             *         perform the resource action
543             */
544            public boolean hasActionId(
545                    ResourcePermission resourcePermission, ResourceAction resourceAction) {
546    
547                    long actionIds = resourcePermission.getActionIds();
548                    long bitwiseValue = resourceAction.getBitwiseValue();
549    
550                    if ((actionIds & bitwiseValue) == bitwiseValue) {
551                            return true;
552                    }
553                    else {
554                            return false;
555                    }
556            }
557    
558            /**
559             * Returns <code>true</code> if the roles have permission at the scope to
560             * perform the action on the resources.
561             *
562             * <p>
563             * Depending on the scope, the value of <code>primKey</code> will have
564             * different meanings. For more information, see {@link
565             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
566             * </p>
567             *
568             * @param  resources the resources
569             * @param  roleIds the primary keys of the roles
570             * @param  actionId the action ID
571             * @return <code>true</code> if any one of the roles has permission to
572             *         perform the action on any one of the resources;
573             *         <code>false</code> otherwise
574             * @throws PortalException if any one of the roles with the primary keys
575             *         could not be found or if a resource action with the name and
576             *         action ID could not be found
577             * @throws SystemException if a system exception occurred
578             */
579            public boolean hasResourcePermission(
580                            List<Resource> resources, long[] roleIds, String actionId)
581                    throws PortalException, SystemException {
582    
583                    // Iterate the list of resources in reverse order to test permissions
584                    // from company scope to individual scope because it is more likely that
585                    // a permission is assigned at a higher scope. Optimizing this method
586                    // to one SQL call may actually slow things down since most of the calls
587                    // will pull from the cache after the first request.
588    
589                    for (int i = resources.size() - 1; i >= 0; i--) {
590                            Resource resource = resources.get(i);
591    
592                            if (hasResourcePermission(
593                                            resource.getCompanyId(), resource.getName(),
594                                            resource.getScope(), resource.getPrimKey(), roleIds,
595                                            actionId)) {
596    
597                                    return true;
598                            }
599                    }
600    
601                    return false;
602            }
603    
604            /**
605             * Returns <code>true</code> if the role has permission at the scope to
606             * perform the action on resources of the type.
607             *
608             * <p>
609             * Depending on the scope, the value of <code>primKey</code> will have
610             * different meanings. For more information, see {@link
611             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
612             * </p>
613             *
614             * @param  companyId the primary key of the company
615             * @param  name the resource's name, which can be either a class name or a
616             *         portlet ID
617             * @param  scope the scope
618             * @param  primKey the primary key
619             * @param  roleId the primary key of the role
620             * @param  actionId the action ID
621             * @return <code>true</code> if the role has permission to perform the
622             *         action on the resource; <code>false</code> otherwise
623             * @throws PortalException if a role with the primary key or a resource
624             *         action with the name and action ID could not be found
625             * @throws SystemException if a system exception occurred
626             */
627            public boolean hasResourcePermission(
628                            long companyId, String name, int scope, String primKey, long roleId,
629                            String actionId)
630                    throws PortalException, SystemException {
631    
632                    return hasResourcePermission(
633                            companyId, name, scope, primKey, new long[] {roleId}, actionId);
634            }
635    
636            /**
637             * Returns <code>true</code> if the roles have permission at the scope to
638             * perform the action on resources of the type.
639             *
640             * <p>
641             * Depending on the scope, the value of <code>primKey</code> will have
642             * different meanings. For more information, see {@link
643             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
644             * </p>
645             *
646             * @param  companyId the primary key of the company
647             * @param  name the resource's name, which can be either a class name or a
648             *         portlet ID
649             * @param  scope the scope
650             * @param  primKey the primary key
651             * @param  roleIds the primary keys of the roles
652             * @param  actionId the action ID
653             * @return <code>true</code> if any one of the roles has permission to
654             *         perform the action on the resource; <code>false</code> otherwise
655             * @throws PortalException if any one of the roles with the primary keys
656             *         could not be found or if a resource action with the name and
657             *         action ID could not be found
658             * @throws SystemException if a system exception occurred
659             */
660            public boolean hasResourcePermission(
661                            long companyId, String name, int scope, String primKey,
662                            long[] roleIds, String actionId)
663                    throws PortalException, SystemException {
664    
665                    ResourceAction resourceAction =
666                            resourceActionLocalService.getResourceAction(name, actionId);
667    
668                    DB db = DBFactoryUtil.getDB();
669    
670                    String dbType = db.getType();
671    
672                    if ((roleIds.length >
673                                    PropsValues.
674                                            PERMISSIONS_ROLE_RESOURCE_PERMISSION_QUERY_THRESHOLD) &&
675                            !dbType.equals(DB.TYPE_DERBY) &&
676                            !dbType.equals(DB.TYPE_JDATASTORE) &&
677                            !dbType.equals(DB.TYPE_SAP)) {
678    
679                            int count = resourcePermissionFinder.countByC_N_S_P_R_A(
680                                    companyId, name, scope, primKey, roleIds,
681                                    resourceAction.getBitwiseValue());
682    
683                            if (count > 0) {
684                                    return true;
685                            }
686                    }
687                    else {
688                            List<ResourcePermission> resourcePermissions =
689                                    resourcePermissionPersistence.findByC_N_S_P_R(
690                                            companyId, name, scope, primKey, roleIds);
691    
692                            if (resourcePermissions.isEmpty()) {
693                                    return false;
694                            }
695    
696                            for (ResourcePermission resourcePermission : resourcePermissions) {
697                                    if (hasActionId(resourcePermission, resourceAction)) {
698                                            return true;
699                                    }
700                            }
701    
702                    }
703    
704                    return false;
705            }
706    
707            public boolean[] hasResourcePermissions(
708                            long companyId, String name, int scope, String primKey,
709                            long[] roleIds, String actionId)
710                    throws PortalException, SystemException {
711    
712                    ResourceAction resourceAction =
713                            resourceActionLocalService.getResourceAction(name, actionId);
714    
715                    List<ResourcePermission> resourcePermissions =
716                            resourcePermissionPersistence.findByC_N_S_P_R(
717                                    companyId, name, scope, primKey, roleIds);
718    
719                    boolean[] hasResourcePermissions = new boolean[roleIds.length];
720    
721                    if (resourcePermissions.isEmpty()) {
722                            return hasResourcePermissions;
723                    }
724    
725                    for (ResourcePermission resourcePermission : resourcePermissions) {
726                            if (hasActionId(resourcePermission, resourceAction)) {
727                                    long roleId = resourcePermission.getRoleId();
728    
729                                    for (int i = 0; i < roleIds.length; i++) {
730                                            if (roleIds[i] == roleId) {
731                                                    hasResourcePermissions[i] = true;
732                                            }
733                                    }
734                            }
735                    }
736    
737                    return hasResourcePermissions;
738            }
739    
740            /**
741             * Returns <code>true</code> if the role has permission at the scope to
742             * perform the action on the resource.
743             *
744             * <p>
745             * Depending on the scope, the value of <code>primKey</code> will have
746             * different meanings. For more information, see {@link
747             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
748             * </p>
749             *
750             * @param  companyId the primary key of the company
751             * @param  name the resource's name, which can be either a class name or a
752             *         portlet ID
753             * @param  scope the scope
754             * @param  roleId the primary key of the role
755             * @param  actionId the action ID
756             * @return <code>true</code> if the role has permission to perform the
757             *         action on the resource; <code>false</code> otherwise
758             * @throws PortalException if a role with the primary key or a resource
759             *         action with the name and action ID could not be found
760             * @throws SystemException if a system exception occurred
761             */
762            public boolean hasScopeResourcePermission(
763                            long companyId, String name, int scope, long roleId,
764                            String actionId)
765                    throws PortalException, SystemException {
766    
767                    List<ResourcePermission> resourcePermissions =
768                            resourcePermissionPersistence.findByC_N_S(companyId, name, scope);
769    
770                    for (ResourcePermission resourcePermission : resourcePermissions) {
771                            if (hasResourcePermission(
772                                            companyId, name, scope, resourcePermission.getPrimKey(),
773                                            roleId, actionId)) {
774    
775                                    return true;
776                            }
777                    }
778    
779                    return false;
780            }
781    
782            /**
783             * Reassigns all the resource permissions from the source role to the
784             * destination role, and deletes the source role.
785             *
786             * @param  fromRoleId the primary key of the source role
787             * @param  toRoleId the primary key of the destination role
788             * @throws PortalException if a role with the primary key could not be found
789             * @throws SystemException if a system exception occurred
790             */
791            public void mergePermissions(long fromRoleId, long toRoleId)
792                    throws PortalException, SystemException {
793    
794                    Role fromRole = rolePersistence.findByPrimaryKey(fromRoleId);
795                    Role toRole = rolePersistence.findByPrimaryKey(toRoleId);
796    
797                    if (fromRole.getType() != toRole.getType()) {
798                            throw new PortalException("Role types are mismatched");
799                    }
800                    else if (PortalUtil.isSystemRole(toRole.getName())) {
801                            throw new PortalException("Cannot move permissions to system role");
802                    }
803                    else if (PortalUtil.isSystemRole(fromRole.getName())) {
804                            throw new PortalException(
805                                    "Cannot move permissions from system role");
806                    }
807    
808                    List<ResourcePermission> resourcePermissions =
809                            getRoleResourcePermissions(fromRoleId);
810    
811                    for (ResourcePermission resourcePermission : resourcePermissions) {
812                            resourcePermission.setRoleId(toRoleId);
813    
814                            resourcePermissionPersistence.update(resourcePermission);
815                    }
816    
817                    roleLocalService.deleteRole(fromRoleId);
818    
819                    PermissionCacheUtil.clearCache();
820            }
821    
822            /**
823             * Grants the role default permissions to all the resources of the type and
824             * at the scope stored in the resource permission, deletes the resource
825             * permission, and deletes the resource permission's role if it has no
826             * permissions remaining.
827             *
828             * @param  resourcePermissionId the primary key of the resource permission
829             * @param  toRoleId the primary key of the role
830             * @throws PortalException if a resource permission or role with the primary
831             *         key could not be found
832             * @throws SystemException if a system exception occurred
833             */
834            public void reassignPermissions(long resourcePermissionId, long toRoleId)
835                    throws PortalException, SystemException {
836    
837                    ResourcePermission resourcePermission = getResourcePermission(
838                            resourcePermissionId);
839    
840                    long companyId = resourcePermission.getCompanyId();
841                    String name = resourcePermission.getName();
842                    int scope = resourcePermission.getScope();
843                    String primKey = resourcePermission.getPrimKey();
844                    long fromRoleId = resourcePermission.getRoleId();
845    
846                    Role toRole = roleLocalService.getRole(toRoleId);
847    
848                    List<String> actionIds = null;
849    
850                    if (toRole.getType() == RoleConstants.TYPE_REGULAR) {
851                            actionIds = ResourceActionsUtil.getModelResourceActions(name);
852                    }
853                    else {
854                            actionIds = ResourceActionsUtil.getModelResourceGroupDefaultActions(
855                                    name);
856                    }
857    
858                    setResourcePermissions(
859                            companyId, name, scope, primKey, toRoleId,
860                            actionIds.toArray(new String[actionIds.size()]));
861    
862                    resourcePermissionPersistence.remove(resourcePermissionId);
863    
864                    List<ResourcePermission> resourcePermissions =
865                            getRoleResourcePermissions(fromRoleId);
866    
867                    if (resourcePermissions.isEmpty()) {
868                            roleLocalService.deleteRole(fromRoleId);
869                    }
870            }
871    
872            /**
873             * Revokes permission at the scope from the role to perform the action on
874             * resources of the type. For example, this method could be used to revoke a
875             * group scope permission to edit blog posts.
876             *
877             * <p>
878             * Depending on the scope, the value of <code>primKey</code> will have
879             * different meanings. For more information, see {@link
880             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
881             * </p>
882             *
883             * @param  companyId the primary key of the company
884             * @param  name the resource's name, which can be either a class name or a
885             *         portlet ID
886             * @param  scope the scope
887             * @param  primKey the primary key
888             * @param  roleId the primary key of the role
889             * @param  actionId the action ID
890             * @throws PortalException if a role with the primary key or a resource
891             *         action with the name and action ID could not be found
892             * @throws SystemException if a system exception occurred
893             */
894            public void removeResourcePermission(
895                            long companyId, String name, int scope, String primKey, long roleId,
896                            String actionId)
897                    throws PortalException, SystemException {
898    
899                    updateResourcePermission(
900                            companyId, name, scope, primKey, roleId, 0, new String[] {actionId},
901                            ResourcePermissionConstants.OPERATOR_REMOVE);
902    
903                    PermissionCacheUtil.clearCache();
904            }
905    
906            /**
907             * Revokes all permissions at the scope from the role to perform the action
908             * on resources of the type. For example, this method could be used to
909             * revoke all individual scope permissions to edit blog posts from site
910             * members.
911             *
912             * @param  companyId the primary key of the company
913             * @param  name the resource's name, which can be either a class name or a
914             *         portlet ID
915             * @param  scope the scope
916             * @param  roleId the primary key of the role
917             * @param  actionId the action ID
918             * @throws PortalException if a role with the primary key or a resource
919             *         action with the name and action ID could not be found
920             * @throws SystemException if a system exception occurred
921             */
922            public void removeResourcePermissions(
923                            long companyId, String name, int scope, long roleId,
924                            String actionId)
925                    throws PortalException, SystemException {
926    
927                    List<ResourcePermission> resourcePermissions =
928                            resourcePermissionPersistence.findByC_N_S(companyId, name, scope);
929    
930                    for (ResourcePermission resourcePermission : resourcePermissions) {
931                            updateResourcePermission(
932                                    companyId, name, scope, resourcePermission.getPrimKey(), roleId,
933                                    0, new String[] {actionId},
934                                    ResourcePermissionConstants.OPERATOR_REMOVE);
935                    }
936    
937                    PermissionCacheUtil.clearCache();
938            }
939    
940            /**
941             * Updates the role's permissions at the scope, setting the actions that can
942             * be performed on resources of the type, also setting the owner of any
943             * newly created resource permissions. Existing actions are replaced.
944             *
945             * <p>
946             * This method can be used to set permissions at any scope, but it is
947             * generally only used at the individual scope. For example, it could be
948             * used to set the guest permissions on a blog post.
949             * </p>
950             *
951             * <p>
952             * Depending on the scope, the value of <code>primKey</code> will have
953             * different meanings. For more information, see {@link
954             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
955             * </p>
956             *
957             * @param  companyId the primary key of the company
958             * @param  name the resource's name, which can be either a class name or a
959             *         portlet ID
960             * @param  scope the scope
961             * @param  primKey the primary key
962             * @param  roleId the primary key of the role
963             * @param  ownerId the primary key of the owner (generally the user that
964             *         created the resource)
965             * @param  actionIds the action IDs of the actions
966             * @throws PortalException if a role with the primary key or a resource
967             *         action with the name and action ID could not be found
968             * @throws SystemException if a system exception occurred
969             */
970            public void setOwnerResourcePermissions(
971                            long companyId, String name, int scope, String primKey, long roleId,
972                            long ownerId, String[] actionIds)
973                    throws PortalException, SystemException {
974    
975                    updateResourcePermission(
976                            companyId, name, scope, primKey, roleId, ownerId, actionIds,
977                            ResourcePermissionConstants.OPERATOR_SET);
978            }
979    
980            /**
981             * Updates the role's permissions at the scope, setting the actions that can
982             * be performed on resources of the type. Existing actions are replaced.
983             *
984             * <p>
985             * This method can be used to set permissions at any scope, but it is
986             * generally only used at the individual scope. For example, it could be
987             * used to set the guest permissions on a blog post.
988             * </p>
989             *
990             * <p>
991             * Depending on the scope, the value of <code>primKey</code> will have
992             * different meanings. For more information, see {@link
993             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
994             * </p>
995             *
996             * @param  companyId the primary key of the company
997             * @param  name the resource's name, which can be either a class name or a
998             *         portlet ID
999             * @param  scope the scope
1000             * @param  primKey the primary key
1001             * @param  roleId the primary key of the role
1002             * @param  actionIds the action IDs of the actions
1003             * @throws PortalException if a role with the primary key or a resource
1004             *         action with the name and action ID could not be found
1005             * @throws SystemException if a system exception occurred
1006             */
1007            public void setResourcePermissions(
1008                            long companyId, String name, int scope, String primKey, long roleId,
1009                            String[] actionIds)
1010                    throws PortalException, SystemException {
1011    
1012                    updateResourcePermission(
1013                            companyId, name, scope, primKey, roleId, 0, actionIds,
1014                            ResourcePermissionConstants.OPERATOR_SET);
1015            }
1016    
1017            /**
1018             * Updates the role's permissions at the scope, setting the actions that can
1019             * be performed on resources of the type. Existing actions are replaced.
1020             *
1021             * <p>
1022             * This method can be used to set permissions at any scope, but it is
1023             * generally only used at the individual scope. For example, it could be
1024             * used to set the guest permissions on a blog post.
1025             * </p>
1026             *
1027             * <p>
1028             * Depending on the scope, the value of <code>primKey</code> will have
1029             * different meanings. For more information, see {@link
1030             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
1031             * </p>
1032             *
1033             * @param  companyId the primary key of the company
1034             * @param  name the resource's name, which can be either a class name or a
1035             *         portlet ID
1036             * @param  scope the scope
1037             * @param  primKey the primary key
1038             * @param  roleIdsToActionIds a map of role IDs to action IDs of the actions
1039             * @throws PortalException if a role with the primary key or a resource
1040             *         action with the name and action ID could not be found
1041             * @throws SystemException if a system exception occurred
1042             */
1043            public void setResourcePermissions(
1044                            long companyId, String name, int scope, String primKey,
1045                            Map<Long, String[]> roleIdsToActionIds)
1046                    throws PortalException, SystemException {
1047    
1048                    updateResourcePermission(
1049                            companyId, name, scope, primKey, 0, roleIdsToActionIds,
1050                            ResourcePermissionConstants.OPERATOR_SET);
1051            }
1052    
1053            protected void doUpdateResourcePermission(
1054                            long companyId, String name, int scope, String primKey,
1055                            long ownerId, long roleId, String[] actionIds, int operator)
1056                    throws PortalException, SystemException {
1057    
1058                    ResourcePermission resourcePermission = null;
1059    
1060                    Map<Long, ResourcePermission> resourcePermissionsMap =
1061                            ResourcePermissionsThreadLocal.getResourcePermissions();
1062    
1063                    if (resourcePermissionsMap != null) {
1064                            resourcePermission = resourcePermissionsMap.get(roleId);
1065                    }
1066                    else {
1067                            List<ResourcePermission> resourcePermissions =
1068                                    resourcePermissionPersistence.findByC_N_S_P_R(
1069                                            companyId, name, scope, primKey, roleId);
1070    
1071                            if (!resourcePermissions.isEmpty()) {
1072                                    resourcePermission = resourcePermissions.get(0);
1073                            }
1074                    }
1075    
1076                    if (resourcePermission == null) {
1077                            if (((operator == ResourcePermissionConstants.OPERATOR_ADD) ||
1078                                     (operator == ResourcePermissionConstants.OPERATOR_SET)) &&
1079                                    (actionIds.length == 0)) {
1080    
1081                                    return;
1082                            }
1083    
1084                            if (operator == ResourcePermissionConstants.OPERATOR_REMOVE) {
1085                                    return;
1086                            }
1087    
1088                            long resourcePermissionId = counterLocalService.increment(
1089                                    ResourcePermission.class.getName());
1090    
1091                            resourcePermission = resourcePermissionPersistence.create(
1092                                    resourcePermissionId);
1093    
1094                            resourcePermission.setCompanyId(companyId);
1095                            resourcePermission.setName(name);
1096                            resourcePermission.setScope(scope);
1097                            resourcePermission.setPrimKey(primKey);
1098                            resourcePermission.setRoleId(roleId);
1099                            resourcePermission.setOwnerId(ownerId);
1100                    }
1101    
1102                    long actionIdsLong = resourcePermission.getActionIds();
1103    
1104                    if (operator == ResourcePermissionConstants.OPERATOR_SET) {
1105                            actionIdsLong = 0;
1106                    }
1107    
1108                    for (String actionId : actionIds) {
1109                            if (actionId == null) {
1110                                    break;
1111                            }
1112    
1113                            ResourceAction resourceAction =
1114                                    resourceActionLocalService.getResourceAction(name, actionId);
1115    
1116                            if ((operator == ResourcePermissionConstants.OPERATOR_ADD) ||
1117                                    (operator == ResourcePermissionConstants.OPERATOR_SET)) {
1118    
1119                                    actionIdsLong |= resourceAction.getBitwiseValue();
1120                            }
1121                            else {
1122                                    actionIdsLong =
1123                                            actionIdsLong & (~resourceAction.getBitwiseValue());
1124                            }
1125                    }
1126    
1127                    resourcePermission.setActionIds(actionIdsLong);
1128    
1129                    resourcePermissionPersistence.update(resourcePermission);
1130    
1131                    PermissionCacheUtil.clearCache();
1132    
1133                    SearchEngineUtil.updatePermissionFields(name, primKey);
1134            }
1135    
1136            protected void doUpdateResourcePermission(
1137                            long companyId, String name, int scope, String primKey,
1138                            long ownerId, Map<Long, String[]> roleIdsToActionIds, int operator)
1139                    throws PortalException, SystemException {
1140    
1141                    boolean flushEnabled = PermissionThreadLocal.isFlushEnabled();
1142    
1143                    PermissionThreadLocal.setIndexEnabled(false);
1144    
1145                    try {
1146                            for (Map.Entry<Long, String[]> entry :
1147                                            roleIdsToActionIds.entrySet()) {
1148    
1149                                    long roleId = entry.getKey();
1150                                    String[] actionIds = entry.getValue();
1151    
1152                                    doUpdateResourcePermission(
1153                                            companyId, name, scope, primKey, ownerId, roleId, actionIds,
1154                                            operator);
1155                            }
1156                    }
1157                    finally {
1158                            PermissionThreadLocal.setIndexEnabled(flushEnabled);
1159    
1160                            PermissionCacheUtil.clearCache();
1161    
1162                            SearchEngineUtil.updatePermissionFields(name, primKey);
1163                    }
1164            }
1165    
1166            /**
1167             * Updates the role's permissions at the scope, either adding to, removing
1168             * from, or setting the actions that can be performed on resources of the
1169             * type. Automatically creates a new resource permission if none exists, or
1170             * deletes the existing resource permission if it no longer grants
1171             * permissions to perform any action.
1172             *
1173             * <p>
1174             * Depending on the scope, the value of <code>primKey</code> will have
1175             * different meanings. For more information, see {@link
1176             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
1177             * </p>
1178             *
1179             * @param  companyId the primary key of the company
1180             * @param  name the resource's name, which can be either a class name or a
1181             *         portlet ID
1182             * @param  scope the scope
1183             * @param  primKey the primary key
1184             * @param  roleId the primary key of the role
1185             * @param  ownerId the primary key of the owner
1186             * @param  actionIds the action IDs of the actions
1187             * @param  operator whether to add to, remove from, or set/replace the
1188             *         existing actions. Possible values can be found in {@link
1189             *         ResourcePermissionConstants}.
1190             * @throws PortalException if a role with the primary key or a resource
1191             *         action with the name and action ID could not be found
1192             * @throws SystemException if a system exception occurred
1193             */
1194            protected void updateResourcePermission(
1195                            long companyId, String name, int scope, String primKey, long roleId,
1196                            long ownerId, String[] actionIds, int operator)
1197                    throws PortalException, SystemException {
1198    
1199                    DB db = DBFactoryUtil.getDB();
1200    
1201                    String dbType = db.getType();
1202    
1203                    if (!dbType.equals(DB.TYPE_HYPERSONIC)) {
1204                            doUpdateResourcePermission(
1205                                    companyId, name, scope, primKey, ownerId, roleId, actionIds,
1206                                    operator);
1207    
1208                            return;
1209                    }
1210    
1211                    StringBundler sb = new StringBundler(9);
1212    
1213                    sb.append(companyId);
1214                    sb.append(StringPool.POUND);
1215                    sb.append(name);
1216                    sb.append(StringPool.POUND);
1217                    sb.append(scope);
1218                    sb.append(StringPool.POUND);
1219                    sb.append(primKey);
1220                    sb.append(StringPool.POUND);
1221                    sb.append(roleId);
1222    
1223                    Class<?> clazz = getClass();
1224    
1225                    String groupName = clazz.getName();
1226    
1227                    String key = sb.toString();
1228    
1229                    Lock lock = LockRegistry.allocateLock(groupName, key);
1230    
1231                    lock.lock();
1232    
1233                    try {
1234                            doUpdateResourcePermission(
1235                                    companyId, name, scope, primKey, ownerId, roleId, actionIds,
1236                                    operator);
1237                    }
1238                    finally {
1239                            lock.unlock();
1240    
1241                            LockRegistry.freeLock(groupName, key);
1242                    }
1243            }
1244    
1245            /**
1246             * Updates the role's permissions at the scope, either adding to, removing
1247             * from, or setting the actions that can be performed on resources of the
1248             * type. Automatically creates a new resource permission if none exists, or
1249             * deletes the existing resource permission if it no longer grants
1250             * permissions to perform any action.
1251             *
1252             * <p>
1253             * Depending on the scope, the value of <code>primKey</code> will have
1254             * different meanings. For more information, see {@link
1255             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
1256             * </p>
1257             *
1258             * @param  companyId the primary key of the company
1259             * @param  name the resource's name, which can be either a class name or a
1260             *         portlet ID
1261             * @param  scope the scope
1262             * @param  primKey the primary key
1263             * @param  ownerId the primary key of the owner
1264             * @param  operator whether to add to, remove from, or set/replace the
1265             *         existing actions. Possible values can be found in {@link
1266             *         ResourcePermissionConstants}.
1267             * @throws PortalException if a role with the primary key or a resource
1268             *         action with the name and action ID could not be found
1269             * @throws SystemException if a system exception occurred
1270             */
1271            protected void updateResourcePermission(
1272                            long companyId, String name, int scope, String primKey,
1273                            long ownerId, Map<Long, String[]> roleIdsToActionIds, int operator)
1274                    throws PortalException, SystemException {
1275    
1276                    DB db = DBFactoryUtil.getDB();
1277    
1278                    String dbType = db.getType();
1279    
1280                    if (!dbType.equals(DB.TYPE_HYPERSONIC)) {
1281                            doUpdateResourcePermission(
1282                                    companyId, name, scope, primKey, ownerId, roleIdsToActionIds,
1283                                    operator);
1284    
1285                            return;
1286                    }
1287    
1288                    StringBundler sb = new StringBundler(9);
1289    
1290                    sb.append(companyId);
1291                    sb.append(StringPool.POUND);
1292                    sb.append(name);
1293                    sb.append(StringPool.POUND);
1294                    sb.append(scope);
1295                    sb.append(StringPool.POUND);
1296                    sb.append(primKey);
1297                    sb.append(StringPool.POUND);
1298                    sb.append(StringUtil.merge(roleIdsToActionIds.keySet()));
1299    
1300                    Class<?> clazz = getClass();
1301    
1302                    String groupName = clazz.getName();
1303    
1304                    String key = sb.toString();
1305    
1306                    Lock lock = LockRegistry.allocateLock(groupName, key);
1307    
1308                    lock.lock();
1309    
1310                    try {
1311                            doUpdateResourcePermission(
1312                                    companyId, name, scope, primKey, ownerId, roleIdsToActionIds,
1313                                    operator);
1314                    }
1315                    finally {
1316                            lock.unlock();
1317    
1318                            LockRegistry.freeLock(groupName, key);
1319                    }
1320            }
1321    
1322    }