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