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