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 name
165             *        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 ResourcePermission fetchResourcePermission(
328                    long companyId, String name, int scope, String primKey, long roleId) {
329    
330                    return resourcePermissionPersistence.fetchByC_N_S_P_R(
331                            companyId, name, scope, primKey, roleId);
332            }
333    
334            @Override
335            public Map<Long, Set<String>> getAvailableResourcePermissionActionIds(
336                    long companyId, String name, int scope, String primKey,
337                    Collection<String> actionIds) {
338    
339                    if (actionIds.isEmpty()) {
340                            return Collections.emptyMap();
341                    }
342    
343                    List<ResourcePermission> resourcePermissions = getResourcePermissions(
344                            companyId, name, scope, primKey);
345    
346                    Map<Long, Set<String>> roleIdsToActionIds =
347                            new HashMap<Long, Set<String>>(resourcePermissions.size());
348    
349                    for (ResourcePermission resourcePermission : resourcePermissions) {
350                            if (resourcePermission.getActionIds() == 0) {
351                                    continue;
352                            }
353    
354                            Set<String> availableActionIds = new HashSet<String>(
355                                    actionIds.size());
356    
357                            for (String actionId : actionIds) {
358                                    if (resourcePermission.hasActionId(actionId)) {
359                                            availableActionIds.add(actionId);
360                                    }
361                            }
362    
363                            if (availableActionIds.size() > 0) {
364                                    roleIdsToActionIds.put(
365                                            resourcePermission.getRoleId(), availableActionIds);
366                            }
367                    }
368    
369                    return roleIdsToActionIds;
370            }
371    
372            /**
373             * Returns the intersection of action IDs the role has permission at the
374             * scope to perform on resources of the type.
375             *
376             * @param  companyId he primary key of the company
377             * @param  name the resource's name, which can be either a class name or a
378             *         portlet ID
379             * @param  scope the scope
380             * @param  primKey the primary key
381             * @param  roleId the primary key of the role
382             * @param  actionIds the action IDs
383             * @return the intersection of action IDs the role has permission at the
384             *         scope to perform on resources of the type
385             * @throws PortalException if a resouce action could not be found for any
386             *         one of the actions on the resource
387             */
388            @Override
389            public List<String> getAvailableResourcePermissionActionIds(
390                            long companyId, String name, int scope, String primKey, long roleId,
391                            Collection<String> actionIds)
392                    throws PortalException {
393    
394                    ResourcePermission resourcePermission =
395                            resourcePermissionPersistence.fetchByC_N_S_P_R(
396                                    companyId, name, scope, primKey, roleId);
397    
398                    if (resourcePermission == null) {
399                            return Collections.emptyList();
400                    }
401    
402                    List<String> availableActionIds = new ArrayList<String>(
403                            actionIds.size());
404    
405                    for (String actionId : actionIds) {
406                            ResourceAction resourceAction =
407                                    resourceActionLocalService.getResourceAction(name, actionId);
408    
409                            if (hasActionId(resourcePermission, resourceAction)) {
410                                    availableActionIds.add(actionId);
411                            }
412                    }
413    
414                    return availableActionIds;
415            }
416    
417            /**
418             * @deprecated As of 7.0.0, replaced by {@link
419             *             #getAvailableResourcePermissionActionIds(long, String, int,
420             *             String, Collection)}
421             */
422            @Deprecated
423            @Override
424            public Map<Long, Set<String>> getAvailableResourcePermissionActionIds(
425                    long companyId, String name, int scope, String primKey, long[] roleIds,
426                    Collection<String> actionIds) {
427    
428                    return getAvailableResourcePermissionActionIds(
429                            companyId, name, scope, primKey, new ArrayList<String>(actionIds));
430            }
431    
432            /**
433             * Returns the resource permission for the role at the scope to perform the
434             * actions on resources of the type.
435             *
436             * @param  companyId the primary key of the company
437             * @param  name the resource's name, which can be either a class name or a
438             *         portlet ID
439             * @param  scope the scope
440             * @param  primKey the primary key
441             * @param  roleId the primary key of the role
442             * @return the resource permission for the role at the scope to perform the
443             *         actions on resources of the type
444             * @throws PortalException if no matching resources could be found
445             */
446            @Override
447            public ResourcePermission getResourcePermission(
448                            long companyId, String name, int scope, String primKey, long roleId)
449                    throws PortalException {
450    
451                    return resourcePermissionPersistence.findByC_N_S_P_R(
452                            companyId, name, scope, primKey, roleId);
453            }
454    
455            /**
456             * Returns all the resource permissions at the scope of the type.
457             *
458             * @param  companyId the primary key of the company
459             * @param  name the resource's name, which can be either a class name or a
460             *         portlet ID
461             * @param  scope the scope
462             * @param  primKey the primary key
463             * @return the resource permissions at the scope of the type
464             */
465            @Override
466            public List<ResourcePermission> getResourcePermissions(
467                    long companyId, String name, int scope, String primKey) {
468    
469                    return resourcePermissionPersistence.findByC_N_S_P(
470                            companyId, name, scope, primKey);
471            }
472    
473            /**
474             * Returns the number of resource permissions at the scope of the type.
475             *
476             * @param  companyId the primary key of the company
477             * @param  name the resource's name, which can be either a class name or a
478             *         portlet ID
479             * @param  scope the scope
480             * @param  primKey the primary key
481             * @return the number of resource permissions at the scope of the type
482             */
483            @Override
484            public int getResourcePermissionsCount(
485                    long companyId, String name, int scope, String primKey) {
486    
487                    return resourcePermissionPersistence.countByC_N_S_P(
488                            companyId, name, scope, primKey);
489            }
490    
491            /**
492             * Returns the resource permissions that apply to the resource.
493             *
494             * @param  companyId the primary key of the resource's company
495             * @param  groupId the primary key of the resource's group
496             * @param  name the resource's name, which can be either a class name or a
497             *         portlet ID
498             * @param  primKey the primary key of the resource
499             * @return the resource permissions associated with the resource
500             */
501            @Override
502            public List<ResourcePermission> getResourceResourcePermissions(
503                    long companyId, long groupId, String name, String primKey) {
504    
505                    return resourcePermissionFinder.findByResource(
506                            companyId, groupId, name, primKey);
507            }
508    
509            /**
510             * Returns all the resource permissions for the role.
511             *
512             * @param  roleId the primary key of the role
513             * @return the resource permissions for the role
514             */
515            @Override
516            public List<ResourcePermission> getRoleResourcePermissions(long roleId) {
517                    return resourcePermissionPersistence.findByRoleId(roleId);
518            }
519    
520            /**
521             * Returns a range of all the resource permissions for the role at the
522             * scopes.
523             *
524             * <p>
525             * Useful when paginating results. Returns a maximum of <code>end -
526             * start</code> instances. <code>start</code> and <code>end</code> are not
527             * primary keys, they are indexes in the result set. Thus, <code>0</code>
528             * refers to the first result in the set. Setting both <code>start</code>
529             * and <code>end</code> to {@link
530             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
531             * result set.
532             * </p>
533             *
534             * @param  roleId the primary key of the role
535             * @param  scopes the scopes
536             * @param  start the lower bound of the range of results
537             * @param  end the upper bound of the range of results (not inclusive)
538             * @return the range of resource permissions for the role at the scopes
539             */
540            @Override
541            public List<ResourcePermission> getRoleResourcePermissions(
542                    long roleId, int[] scopes, int start, int end) {
543    
544                    return resourcePermissionFinder.findByR_S(roleId, scopes, start, end);
545            }
546    
547            /**
548             * Returns all the resource permissions where scope = any &#63;.
549             *
550             * <p>
551             * Useful when paginating results. Returns a maximum of <code>end -
552             * start</code> instances. <code>start</code> and <code>end</code> are not
553             * primary keys, they are indexes in the result set. Thus, <code>0</code>
554             * refers to the first result in the set. Setting both <code>start</code>
555             * and <code>end</code> to {@link
556             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
557             * result set.
558             * </p>
559             *
560             * @param  scopes the scopes
561             * @return the resource permissions where scope = any &#63;
562             */
563            @Override
564            public List<ResourcePermission> getScopeResourcePermissions(int[] scopes) {
565                    return resourcePermissionPersistence.findByScope(scopes);
566            }
567    
568            /**
569             * Returns <code>true</code> if the resource permission grants permission to
570             * perform the resource action. Note that this method does not ensure that
571             * the resource permission refers to the same type of resource as the
572             * resource action.
573             *
574             * @param  resourcePermission the resource permission
575             * @param  resourceAction the resource action
576             * @return <code>true</code> if the resource permission grants permission to
577             *         perform the resource action
578             */
579            @Override
580            public boolean hasActionId(
581                    ResourcePermission resourcePermission, ResourceAction resourceAction) {
582    
583                    long actionIds = resourcePermission.getActionIds();
584                    long bitwiseValue = resourceAction.getBitwiseValue();
585    
586                    if ((actionIds & bitwiseValue) == bitwiseValue) {
587                            return true;
588                    }
589                    else {
590                            return false;
591                    }
592            }
593    
594            /**
595             * Returns <code>true</code> if the roles have permission at the scope to
596             * perform the action on the resources.
597             *
598             * <p>
599             * Depending on the scope, the value of <code>primKey</code> will have
600             * different meanings. For more information, see {@link
601             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
602             * </p>
603             *
604             * @param  resources the resources
605             * @param  roleIds the primary keys of the roles
606             * @param  actionId the action ID
607             * @return <code>true</code> if any one of the roles has permission to
608             *         perform the action on any one of the resources;
609             *         <code>false</code> otherwise
610             * @throws PortalException if any one of the roles with the primary keys
611             *         could not be found or if a resource action with the name and
612             *         action ID could not be found
613             */
614            @Override
615            public boolean hasResourcePermission(
616                            List<Resource> resources, long[] roleIds, String actionId)
617                    throws PortalException {
618    
619                    if (roleIds.length == 0) {
620                            return false;
621                    }
622    
623                    int size = resources.size();
624    
625                    if (size < 2) {
626                            throw new IllegalArgumentException(
627                                    "The list of resources must contain at least two values");
628                    }
629    
630                    Resource firstResource = resources.get(0);
631    
632                    if (firstResource.getScope() != ResourceConstants.SCOPE_INDIVIDUAL) {
633                            throw new IllegalArgumentException(
634                                    "The first resource must be an individual scope");
635                    }
636    
637                    Resource lastResource = resources.get(size - 1);
638    
639                    if (lastResource.getScope() != ResourceConstants.SCOPE_COMPANY) {
640                            throw new IllegalArgumentException(
641                                    "The last resource must be a company scope");
642                    }
643    
644                    // See LPS-47464
645    
646                    if (resourcePermissionPersistence.countByC_N_S_P(
647                                    firstResource.getCompanyId(), firstResource.getName(),
648                                    firstResource.getScope(), firstResource.getPrimKey()) < 1) {
649    
650                            return false;
651                    }
652    
653                    // Iterate the list of resources in reverse order to test permissions
654                    // from company scope to individual scope because it is more likely that
655                    // a permission is assigned at a higher scope. Optimizing this method to
656                    // one SQL call may actually slow things down since most of the calls
657                    // will pull from the cache after the first request.
658    
659                    for (int i = size - 1; i >= 0; i--) {
660                            Resource resource = resources.get(i);
661    
662                            if (hasResourcePermission(
663                                            resource.getCompanyId(), resource.getName(),
664                                            resource.getScope(), resource.getPrimKey(), roleIds,
665                                            actionId)) {
666    
667                                    return true;
668                            }
669                    }
670    
671                    return false;
672            }
673    
674            /**
675             * Returns <code>true</code> if the role has permission at the scope to
676             * perform the action on resources of the type.
677             *
678             * <p>
679             * Depending on the scope, the value of <code>primKey</code> will have
680             * different meanings. For more information, see {@link
681             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
682             * </p>
683             *
684             * @param  companyId the primary key of the company
685             * @param  name the resource's name, which can be either a class name or a
686             *         portlet ID
687             * @param  scope the scope
688             * @param  primKey the primary key
689             * @param  roleId the primary key of the role
690             * @param  actionId the action ID
691             * @return <code>true</code> if the role has permission to perform the
692             *         action on the resource; <code>false</code> otherwise
693             * @throws PortalException if a role with the primary key or a resource
694             *         action with the name and action ID could not be found
695             */
696            @Override
697            public boolean hasResourcePermission(
698                            long companyId, String name, int scope, String primKey, long roleId,
699                            String actionId)
700                    throws PortalException {
701    
702                    ResourcePermission resourcePermission =
703                            resourcePermissionPersistence.fetchByC_N_S_P_R(
704                                    companyId, name, scope, primKey, roleId);
705    
706                    if (resourcePermission == null) {
707                            return false;
708                    }
709    
710                    ResourceAction resourceAction =
711                            resourceActionLocalService.getResourceAction(name, actionId);
712    
713                    if (hasActionId(resourcePermission, resourceAction)) {
714                            return true;
715                    }
716    
717                    return false;
718            }
719    
720            /**
721             * Returns <code>true</code> if the roles have permission at the scope to
722             * perform the action on resources of the type.
723             *
724             * <p>
725             * Depending on the scope, the value of <code>primKey</code> will have
726             * different meanings. For more information, see {@link
727             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
728             * </p>
729             *
730             * @param  companyId the primary key of the company
731             * @param  name the resource's name, which can be either a class name or a
732             *         portlet ID
733             * @param  scope the scope
734             * @param  primKey the primary key
735             * @param  roleIds the primary keys of the roles
736             * @param  actionId the action ID
737             * @return <code>true</code> if any one of the roles has permission to
738             *         perform the action on the resource; <code>false</code> otherwise
739             * @throws PortalException if any one of the roles with the primary keys
740             *         could not be found or if a resource action with the name and
741             *         action ID could not be found
742             */
743            @Override
744            public boolean hasResourcePermission(
745                            long companyId, String name, int scope, String primKey,
746                            long[] roleIds, String actionId)
747                    throws PortalException {
748    
749                    if (roleIds.length == 0) {
750                            return false;
751                    }
752    
753                    ResourceAction resourceAction =
754                            resourceActionLocalService.getResourceAction(name, actionId);
755    
756                    DB db = DBFactoryUtil.getDB();
757    
758                    String dbType = db.getType();
759    
760                    if ((roleIds.length >
761                                    PropsValues.
762                                            PERMISSIONS_ROLE_RESOURCE_PERMISSION_QUERY_THRESHOLD) &&
763                            !dbType.equals(DB.TYPE_DERBY) &&
764                            !dbType.equals(DB.TYPE_JDATASTORE) &&
765                            !dbType.equals(DB.TYPE_SAP)) {
766    
767                            int count = resourcePermissionFinder.countByC_N_S_P_R_A(
768                                    companyId, name, scope, primKey, roleIds,
769                                    resourceAction.getBitwiseValue());
770    
771                            if (count > 0) {
772                                    return true;
773                            }
774                    }
775                    else {
776                            List<ResourcePermission> resourcePermissions =
777                                    resourcePermissionPersistence.findByC_N_S_P_R(
778                                            companyId, name, scope, primKey, roleIds);
779    
780                            if (resourcePermissions.isEmpty()) {
781                                    return false;
782                            }
783    
784                            for (ResourcePermission resourcePermission : resourcePermissions) {
785                                    if (hasActionId(resourcePermission, resourceAction)) {
786                                            return true;
787                                    }
788                            }
789                    }
790    
791                    return false;
792            }
793    
794            @Override
795            public boolean[] hasResourcePermissions(
796                            long companyId, String name, int scope, String primKey,
797                            long[] roleIds, String actionId)
798                    throws PortalException {
799    
800                    boolean[] hasResourcePermissions = new boolean[roleIds.length];
801    
802                    if (roleIds.length == 0) {
803                            return hasResourcePermissions;
804                    }
805    
806                    ResourceAction resourceAction =
807                            resourceActionLocalService.getResourceAction(name, actionId);
808    
809                    List<ResourcePermission> resourcePermissions =
810                            resourcePermissionPersistence.findByC_N_S_P_R(
811                                    companyId, name, scope, primKey, roleIds);
812    
813                    if (resourcePermissions.isEmpty()) {
814                            return hasResourcePermissions;
815                    }
816    
817                    for (ResourcePermission resourcePermission : resourcePermissions) {
818                            if (hasActionId(resourcePermission, resourceAction)) {
819                                    long roleId = resourcePermission.getRoleId();
820    
821                                    for (int i = 0; i < roleIds.length; i++) {
822                                            if (roleIds[i] == roleId) {
823                                                    hasResourcePermissions[i] = true;
824    
825                                                    break;
826                                            }
827                                    }
828                            }
829                    }
830    
831                    return hasResourcePermissions;
832            }
833    
834            /**
835             * Returns <code>true</code> if the role has permission at the scope to
836             * perform the action on the resource.
837             *
838             * <p>
839             * Depending on the scope, the value of <code>primKey</code> will have
840             * different meanings. For more information, see {@link
841             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
842             * </p>
843             *
844             * @param  companyId the primary key of the company
845             * @param  name the resource's name, which can be either a class name or a
846             *         portlet ID
847             * @param  scope the scope
848             * @param  roleId the primary key of the role
849             * @param  actionId the action ID
850             * @return <code>true</code> if the role has permission to perform the
851             *         action on the resource; <code>false</code> otherwise
852             * @throws PortalException if a role with the primary key or a resource
853             *         action with the name and action ID could not be found
854             */
855            @Override
856            public boolean hasScopeResourcePermission(
857                            long companyId, String name, int scope, long roleId,
858                            String actionId)
859                    throws PortalException {
860    
861                    List<ResourcePermission> resourcePermissions =
862                            resourcePermissionPersistence.findByC_N_S(companyId, name, scope);
863    
864                    for (ResourcePermission resourcePermission : resourcePermissions) {
865                            if (hasResourcePermission(
866                                            companyId, name, scope, resourcePermission.getPrimKey(),
867                                            roleId, actionId)) {
868    
869                                    return true;
870                            }
871                    }
872    
873                    return false;
874            }
875    
876            /**
877             * Reassigns all the resource permissions from the source role to the
878             * destination role, and deletes the source role.
879             *
880             * @param  fromRoleId the primary key of the source role
881             * @param  toRoleId the primary key of the destination role
882             * @throws PortalException if a role with the primary key could not be found
883             */
884            @Override
885            public void mergePermissions(long fromRoleId, long toRoleId)
886                    throws PortalException {
887    
888                    Role fromRole = rolePersistence.findByPrimaryKey(fromRoleId);
889                    Role toRole = rolePersistence.findByPrimaryKey(toRoleId);
890    
891                    if (fromRole.getType() != toRole.getType()) {
892                            throw new PortalException("Role types are mismatched");
893                    }
894                    else if (PortalUtil.isSystemRole(toRole.getName())) {
895                            throw new PortalException("Cannot move permissions to system role");
896                    }
897                    else if (PortalUtil.isSystemRole(fromRole.getName())) {
898                            throw new PortalException(
899                                    "Cannot move permissions from system role");
900                    }
901    
902                    List<ResourcePermission> resourcePermissions =
903                            getRoleResourcePermissions(fromRoleId);
904    
905                    for (ResourcePermission resourcePermission : resourcePermissions) {
906                            resourcePermission.setRoleId(toRoleId);
907    
908                            resourcePermissionPersistence.update(resourcePermission);
909                    }
910    
911                    roleLocalService.deleteRole(fromRoleId);
912    
913                    PermissionCacheUtil.clearCache();
914            }
915    
916            /**
917             * Grants the role default permissions to all the resources of the type and
918             * at the scope stored in the resource permission, deletes the resource
919             * permission, and deletes the resource permission's role if it has no
920             * permissions remaining.
921             *
922             * @param  resourcePermissionId the primary key of the resource permission
923             * @param  toRoleId the primary key of the role
924             * @throws PortalException if a resource permission or role with the primary
925             *         key could not be found
926             */
927            @Override
928            public void reassignPermissions(long resourcePermissionId, long toRoleId)
929                    throws PortalException {
930    
931                    ResourcePermission resourcePermission = getResourcePermission(
932                            resourcePermissionId);
933    
934                    long companyId = resourcePermission.getCompanyId();
935                    String name = resourcePermission.getName();
936                    int scope = resourcePermission.getScope();
937                    String primKey = resourcePermission.getPrimKey();
938                    long fromRoleId = resourcePermission.getRoleId();
939    
940                    Role toRole = roleLocalService.getRole(toRoleId);
941    
942                    List<String> actionIds = null;
943    
944                    if (toRole.getType() == RoleConstants.TYPE_REGULAR) {
945                            actionIds = ResourceActionsUtil.getModelResourceActions(name);
946                    }
947                    else {
948                            actionIds = ResourceActionsUtil.getModelResourceGroupDefaultActions(
949                                    name);
950                    }
951    
952                    setResourcePermissions(
953                            companyId, name, scope, primKey, toRoleId,
954                            actionIds.toArray(new String[actionIds.size()]));
955    
956                    resourcePermissionPersistence.remove(resourcePermissionId);
957    
958                    List<ResourcePermission> resourcePermissions =
959                            getRoleResourcePermissions(fromRoleId);
960    
961                    if (resourcePermissions.isEmpty()) {
962                            roleLocalService.deleteRole(fromRoleId);
963                    }
964            }
965    
966            /**
967             * Revokes permission at the scope from the role to perform the action on
968             * resources of the type. For example, this method could be used to revoke a
969             * group scope permission to edit blog posts.
970             *
971             * <p>
972             * Depending on the scope, the value of <code>primKey</code> will have
973             * different meanings. For more information, see {@link
974             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
975             * </p>
976             *
977             * @param  companyId the primary key of the company
978             * @param  name the resource's name, which can be either a class name or a
979             *         portlet ID
980             * @param  scope the scope
981             * @param  primKey the primary key
982             * @param  roleId the primary key of the role
983             * @param  actionId the action ID
984             * @throws PortalException if a role with the primary key or a resource
985             *         action with the name and action ID could not be found
986             */
987            @Override
988            public void removeResourcePermission(
989                            long companyId, String name, int scope, String primKey, long roleId,
990                            String actionId)
991                    throws PortalException {
992    
993                    updateResourcePermission(
994                            companyId, name, scope, primKey, roleId, 0, new String[] {actionId},
995                            ResourcePermissionConstants.OPERATOR_REMOVE);
996    
997                    PermissionCacheUtil.clearCache();
998            }
999    
1000            /**
1001             * Revokes all permissions at the scope from the role to perform the action
1002             * on resources of the type. For example, this method could be used to
1003             * revoke all individual scope permissions to edit blog posts from site
1004             * members.
1005             *
1006             * @param  companyId the primary key of the company
1007             * @param  name the resource's name, which can be either a class name or a
1008             *         portlet ID
1009             * @param  scope the scope
1010             * @param  roleId the primary key of the role
1011             * @param  actionId the action ID
1012             * @throws PortalException if a role with the primary key or a resource
1013             *         action with the name and action ID could not be found
1014             */
1015            @Override
1016            public void removeResourcePermissions(
1017                            long companyId, String name, int scope, long roleId,
1018                            String actionId)
1019                    throws PortalException {
1020    
1021                    List<ResourcePermission> resourcePermissions =
1022                            resourcePermissionPersistence.findByC_N_S(companyId, name, scope);
1023    
1024                    for (ResourcePermission resourcePermission : resourcePermissions) {
1025                            updateResourcePermission(
1026                                    companyId, name, scope, resourcePermission.getPrimKey(), roleId,
1027                                    0, new String[] {actionId},
1028                                    ResourcePermissionConstants.OPERATOR_REMOVE);
1029                    }
1030    
1031                    PermissionCacheUtil.clearCache();
1032            }
1033    
1034            /**
1035             * Updates the role's permissions at the scope, setting the actions that can
1036             * be performed on resources of the type, also setting the owner of any
1037             * newly created resource permissions. Existing actions are replaced.
1038             *
1039             * <p>
1040             * This method can be used to set permissions at any scope, but it is
1041             * generally only used at the individual scope. For example, it could be
1042             * used to set the guest permissions on a blog post.
1043             * </p>
1044             *
1045             * <p>
1046             * Depending on the scope, the value of <code>primKey</code> will have
1047             * different meanings. For more information, see {@link
1048             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
1049             * </p>
1050             *
1051             * @param  companyId the primary key of the company
1052             * @param  name the resource's name, which can be either a class name or a
1053             *         portlet ID
1054             * @param  scope the scope
1055             * @param  primKey the primary key
1056             * @param  roleId the primary key of the role
1057             * @param  ownerId the primary key of the owner (generally the user that
1058             *         created the resource)
1059             * @param  actionIds the action IDs of the actions
1060             * @throws PortalException if a role with the primary key or a resource
1061             *         action with the name and action ID could not be found
1062             */
1063            @Override
1064            public void setOwnerResourcePermissions(
1065                            long companyId, String name, int scope, String primKey, long roleId,
1066                            long ownerId, String[] actionIds)
1067                    throws PortalException {
1068    
1069                    updateResourcePermission(
1070                            companyId, name, scope, primKey, roleId, ownerId, actionIds,
1071                            ResourcePermissionConstants.OPERATOR_SET);
1072            }
1073    
1074            /**
1075             * Updates the role's permissions at the scope, setting the actions that can
1076             * be performed on resources of the type. Existing actions are replaced.
1077             *
1078             * <p>
1079             * This method can be used to set permissions at any scope, but it is
1080             * generally only used at the individual scope. For example, it could be
1081             * used to set the guest permissions on a blog post.
1082             * </p>
1083             *
1084             * <p>
1085             * Depending on the scope, the value of <code>primKey</code> will have
1086             * different meanings. For more information, see {@link
1087             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
1088             * </p>
1089             *
1090             * @param  companyId the primary key of the company
1091             * @param  name the resource's name, which can be either a class name or a
1092             *         portlet ID
1093             * @param  scope the scope
1094             * @param  primKey the primary key
1095             * @param  roleId the primary key of the role
1096             * @param  actionIds the action IDs of the actions
1097             * @throws PortalException if a role with the primary key or a resource
1098             *         action with the name and action ID could not be found
1099             */
1100            @Override
1101            public void setResourcePermissions(
1102                            long companyId, String name, int scope, String primKey, long roleId,
1103                            String[] actionIds)
1104                    throws PortalException {
1105    
1106                    updateResourcePermission(
1107                            companyId, name, scope, primKey, roleId, 0, actionIds,
1108                            ResourcePermissionConstants.OPERATOR_SET);
1109            }
1110    
1111            /**
1112             * Updates the role's permissions at the scope, setting the actions that can
1113             * be performed on resources of the type. Existing actions are replaced.
1114             *
1115             * <p>
1116             * This method can be used to set permissions at any scope, but it is
1117             * generally only used at the individual scope. For example, it could be
1118             * used to set the guest permissions on a blog post.
1119             * </p>
1120             *
1121             * <p>
1122             * Depending on the scope, the value of <code>primKey</code> will have
1123             * different meanings. For more information, see {@link
1124             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
1125             * </p>
1126             *
1127             * @param  companyId the primary key of the company
1128             * @param  name the resource's name, which can be either a class name or a
1129             *         portlet ID
1130             * @param  scope the scope
1131             * @param  primKey the primary key
1132             * @param  roleIdsToActionIds a map of role IDs to action IDs of the actions
1133             * @throws PortalException if a role with the primary key or a resource
1134             *         action with the name and action ID could not be found
1135             */
1136            @Override
1137            public void setResourcePermissions(
1138                            long companyId, String name, int scope, String primKey,
1139                            Map<Long, String[]> roleIdsToActionIds)
1140                    throws PortalException {
1141    
1142                    updateResourcePermission(
1143                            companyId, name, scope, primKey, 0, roleIdsToActionIds);
1144            }
1145    
1146            protected void doUpdateResourcePermission(
1147                            long companyId, String name, int scope, String primKey,
1148                            long ownerId, long roleId, String[] actionIds, int operator,
1149                            boolean fetch)
1150                    throws PortalException {
1151    
1152                    ResourcePermission resourcePermission = null;
1153    
1154                    Map<Long, ResourcePermission> resourcePermissionsMap =
1155                            ResourcePermissionsThreadLocal.getResourcePermissions();
1156    
1157                    if (resourcePermissionsMap != null) {
1158                            resourcePermission = resourcePermissionsMap.get(roleId);
1159                    }
1160                    else if (fetch) {
1161                            resourcePermission = resourcePermissionPersistence.fetchByC_N_S_P_R(
1162                                    companyId, name, scope, primKey, roleId);
1163                    }
1164    
1165                    if (resourcePermission == null) {
1166                            if (((operator == ResourcePermissionConstants.OPERATOR_ADD) ||
1167                                     (operator == ResourcePermissionConstants.OPERATOR_SET)) &&
1168                                    (actionIds.length == 0)) {
1169    
1170                                    return;
1171                            }
1172    
1173                            if (operator == ResourcePermissionConstants.OPERATOR_REMOVE) {
1174                                    return;
1175                            }
1176    
1177                            long resourcePermissionId = counterLocalService.increment(
1178                                    ResourcePermission.class.getName());
1179    
1180                            resourcePermission = resourcePermissionPersistence.create(
1181                                    resourcePermissionId);
1182    
1183                            resourcePermission.setCompanyId(companyId);
1184                            resourcePermission.setName(name);
1185                            resourcePermission.setScope(scope);
1186                            resourcePermission.setPrimKey(primKey);
1187                            resourcePermission.setRoleId(roleId);
1188                            resourcePermission.setOwnerId(ownerId);
1189                    }
1190    
1191                    List<String> unsupportedActionIds = Collections.emptyList();
1192    
1193                    if (((operator == ResourcePermissionConstants.OPERATOR_ADD) ||
1194                             (operator == ResourcePermissionConstants.OPERATOR_SET)) &&
1195                            isGuestRoleId(companyId, roleId)) {
1196    
1197                            unsupportedActionIds =
1198                                    ResourceActionsUtil.getResourceGuestUnsupportedActions(
1199                                            name, name);
1200                    }
1201    
1202                    long actionIdsLong = resourcePermission.getActionIds();
1203    
1204                    if (operator == ResourcePermissionConstants.OPERATOR_SET) {
1205                            actionIdsLong = 0;
1206                    }
1207    
1208                    for (String actionId : actionIds) {
1209                            if (actionId == null) {
1210                                    break;
1211                            }
1212    
1213                            if (unsupportedActionIds.contains(actionId)) {
1214                                    throw new PrincipalException(
1215                                            actionId + "is not supported by role " + roleId);
1216                            }
1217    
1218                            ResourceAction resourceAction =
1219                                    resourceActionLocalService.getResourceAction(name, actionId);
1220    
1221                            if ((operator == ResourcePermissionConstants.OPERATOR_ADD) ||
1222                                    (operator == ResourcePermissionConstants.OPERATOR_SET)) {
1223    
1224                                    actionIdsLong |= resourceAction.getBitwiseValue();
1225                            }
1226                            else {
1227                                    actionIdsLong =
1228                                            actionIdsLong & (~resourceAction.getBitwiseValue());
1229                            }
1230                    }
1231    
1232                    resourcePermission.setActionIds(actionIdsLong);
1233    
1234                    resourcePermissionPersistence.update(resourcePermission);
1235    
1236                    PermissionCacheUtil.clearCache();
1237    
1238                    SearchEngineUtil.updatePermissionFields(name, primKey);
1239            }
1240    
1241            protected void doUpdateResourcePermission(
1242                            long companyId, String name, int scope, String primKey,
1243                            long ownerId, Map<Long, String[]> roleIdsToActionIds)
1244                    throws PortalException {
1245    
1246                    boolean flushEnabled = PermissionThreadLocal.isFlushEnabled();
1247    
1248                    PermissionThreadLocal.setIndexEnabled(false);
1249    
1250                    try {
1251                            long[] roleIds = ArrayUtil.toLongArray(roleIdsToActionIds.keySet());
1252    
1253                            List<ResourcePermission> resourcePermissions =
1254                                    resourcePermissionPersistence.findByC_N_S_P_R(
1255                                            companyId, name, scope, primKey, roleIds);
1256    
1257                            for (ResourcePermission resourcePermission : resourcePermissions) {
1258                                    long roleId = resourcePermission.getRoleId();
1259                                    String[] actionIds = roleIdsToActionIds.remove(roleId);
1260    
1261                                    doUpdateResourcePermission(
1262                                            companyId, name, scope, primKey, ownerId, roleId, actionIds,
1263                                            ResourcePermissionConstants.OPERATOR_SET, true);
1264                            }
1265    
1266                            if (roleIdsToActionIds.isEmpty()) {
1267                                    return;
1268                            }
1269    
1270                            for (Map.Entry<Long, String[]> entry :
1271                                            roleIdsToActionIds.entrySet()) {
1272    
1273                                    long roleId = entry.getKey();
1274                                    String[] actionIds = entry.getValue();
1275    
1276                                    doUpdateResourcePermission(
1277                                            companyId, name, scope, primKey, ownerId, roleId, actionIds,
1278                                            ResourcePermissionConstants.OPERATOR_SET, false);
1279                            }
1280                    }
1281                    finally {
1282                            PermissionThreadLocal.setIndexEnabled(flushEnabled);
1283    
1284                            PermissionCacheUtil.clearCache();
1285    
1286                            SearchEngineUtil.updatePermissionFields(name, primKey);
1287                    }
1288            }
1289    
1290            protected boolean isGuestRoleId(long companyId, long roleId)
1291                    throws PortalException {
1292    
1293                    Role guestRole = roleLocalService.getRole(
1294                            companyId, RoleConstants.GUEST);
1295    
1296                    if (roleId == guestRole.getRoleId()) {
1297                            return true;
1298                    }
1299    
1300                    return false;
1301            }
1302    
1303            /**
1304             * Updates the role's permissions at the scope, either adding to, removing
1305             * from, or setting the actions that can be performed on resources of the
1306             * type. Automatically creates a new resource permission if none exists, or
1307             * deletes the existing resource permission if it no longer grants
1308             * permissions to perform any action.
1309             *
1310             * <p>
1311             * Depending on the scope, the value of <code>primKey</code> will have
1312             * different meanings. For more information, see {@link
1313             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
1314             * </p>
1315             *
1316             * @param  companyId the primary key of the company
1317             * @param  name the resource's name, which can be either a class name or a
1318             *         portlet ID
1319             * @param  scope the scope
1320             * @param  primKey the primary key
1321             * @param  roleId the primary key of the role
1322             * @param  ownerId the primary key of the owner
1323             * @param  actionIds the action IDs of the actions
1324             * @param  operator whether to add to, remove from, or set/replace the
1325             *         existing actions. Possible values can be found in {@link
1326             *         ResourcePermissionConstants}.
1327             * @throws PortalException if a role with the primary key or a resource
1328             *         action with the name and action ID could not be found
1329             */
1330            protected void updateResourcePermission(
1331                            long companyId, String name, int scope, String primKey, long roleId,
1332                            long ownerId, String[] actionIds, int operator)
1333                    throws PortalException {
1334    
1335                    DB db = DBFactoryUtil.getDB();
1336    
1337                    String dbType = db.getType();
1338    
1339                    if (!dbType.equals(DB.TYPE_HYPERSONIC)) {
1340                            doUpdateResourcePermission(
1341                                    companyId, name, scope, primKey, ownerId, roleId, actionIds,
1342                                    operator, true);
1343    
1344                            return;
1345                    }
1346    
1347                    StringBundler sb = new StringBundler(9);
1348    
1349                    sb.append(companyId);
1350                    sb.append(StringPool.POUND);
1351                    sb.append(name);
1352                    sb.append(StringPool.POUND);
1353                    sb.append(scope);
1354                    sb.append(StringPool.POUND);
1355                    sb.append(primKey);
1356                    sb.append(StringPool.POUND);
1357                    sb.append(roleId);
1358    
1359                    Class<?> clazz = getClass();
1360    
1361                    String groupName = clazz.getName();
1362    
1363                    String key = sb.toString();
1364    
1365                    Lock lock = LockRegistry.allocateLock(groupName, key);
1366    
1367                    lock.lock();
1368    
1369                    try {
1370                            doUpdateResourcePermission(
1371                                    companyId, name, scope, primKey, ownerId, roleId, actionIds,
1372                                    operator, true);
1373                    }
1374                    finally {
1375                            lock.unlock();
1376    
1377                            LockRegistry.freeLock(groupName, key);
1378                    }
1379            }
1380    
1381            /**
1382             * Updates the role's permissions at the scope, either adding to, removing
1383             * from, or setting the actions that can be performed on resources of the
1384             * type. Automatically creates a new resource permission if none exists, or
1385             * deletes the existing resource permission if it no longer grants
1386             * permissions to perform any action.
1387             *
1388             * <p>
1389             * Depending on the scope, the value of <code>primKey</code> will have
1390             * different meanings. For more information, see {@link
1391             * com.liferay.portal.model.impl.ResourcePermissionImpl}.
1392             * </p>
1393             *
1394             * @param  companyId the primary key of the company
1395             * @param  name the resource's name, which can be either a class name or a
1396             *         portlet ID
1397             * @param  scope the scope
1398             * @param  primKey the primary key
1399             * @param  ownerId the primary key of the owner
1400             * @throws PortalException if a role with the primary key or a resource
1401             *         action with the name and action ID could not be found
1402             */
1403            protected void updateResourcePermission(
1404                            long companyId, String name, int scope, String primKey,
1405                            long ownerId, Map<Long, String[]> roleIdsToActionIds)
1406                    throws PortalException {
1407    
1408                    DB db = DBFactoryUtil.getDB();
1409    
1410                    String dbType = db.getType();
1411    
1412                    if (!dbType.equals(DB.TYPE_HYPERSONIC)) {
1413                            doUpdateResourcePermission(
1414                                    companyId, name, scope, primKey, ownerId, roleIdsToActionIds);
1415    
1416                            return;
1417                    }
1418    
1419                    StringBundler sb = new StringBundler(9);
1420    
1421                    sb.append(companyId);
1422                    sb.append(StringPool.POUND);
1423                    sb.append(name);
1424                    sb.append(StringPool.POUND);
1425                    sb.append(scope);
1426                    sb.append(StringPool.POUND);
1427                    sb.append(primKey);
1428                    sb.append(StringPool.POUND);
1429                    sb.append(StringUtil.merge(roleIdsToActionIds.keySet()));
1430    
1431                    Class<?> clazz = getClass();
1432    
1433                    String groupName = clazz.getName();
1434    
1435                    String key = sb.toString();
1436    
1437                    Lock lock = LockRegistry.allocateLock(groupName, key);
1438    
1439                    lock.lock();
1440    
1441                    try {
1442                            doUpdateResourcePermission(
1443                                    companyId, name, scope, primKey, ownerId, roleIdsToActionIds);
1444                    }
1445                    finally {
1446                            lock.unlock();
1447    
1448                            LockRegistry.freeLock(groupName, key);
1449                    }
1450            }
1451    
1452            private static final String _FIND_MISSING_RESOURCE_PERMISSIONS =
1453                    ResourcePermissionLocalServiceImpl.class.getName() +
1454                            ".findMissingResourcePermissions";
1455    
1456            private static final String _UPDATE_ACTION_IDS =
1457                    ResourcePermissionLocalServiceImpl.class.getName() + ".updateActionIds";
1458    
1459    }