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