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