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.kernel.dao.db.DB;
018    import com.liferay.portal.kernel.dao.db.DBManagerUtil;
019    import com.liferay.portal.kernel.dao.jdbc.CurrentConnectionUtil;
020    import com.liferay.portal.kernel.dao.orm.ORMException;
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.exception.PortalException;
025    import com.liferay.portal.kernel.exception.ResourceBlocksNotSupportedException;
026    import com.liferay.portal.kernel.exception.SystemException;
027    import com.liferay.portal.kernel.log.Log;
028    import com.liferay.portal.kernel.log.LogFactoryUtil;
029    import com.liferay.portal.kernel.model.AuditedModel;
030    import com.liferay.portal.kernel.model.GroupedModel;
031    import com.liferay.portal.kernel.model.PermissionedModel;
032    import com.liferay.portal.kernel.model.PersistedModel;
033    import com.liferay.portal.kernel.model.ResourceAction;
034    import com.liferay.portal.kernel.model.ResourceBlock;
035    import com.liferay.portal.kernel.model.ResourceBlockConstants;
036    import com.liferay.portal.kernel.model.ResourceBlockPermissionsContainer;
037    import com.liferay.portal.kernel.model.ResourceConstants;
038    import com.liferay.portal.kernel.model.ResourceTypePermission;
039    import com.liferay.portal.kernel.model.Role;
040    import com.liferay.portal.kernel.model.RoleConstants;
041    import com.liferay.portal.kernel.security.auth.PrincipalException;
042    import com.liferay.portal.kernel.security.permission.PermissionThreadLocal;
043    import com.liferay.portal.kernel.security.permission.ResourceActionsUtil;
044    import com.liferay.portal.kernel.security.permission.ResourceBlockIdsBag;
045    import com.liferay.portal.kernel.service.PersistedModelLocalService;
046    import com.liferay.portal.kernel.service.PersistedModelLocalServiceRegistryUtil;
047    import com.liferay.portal.kernel.transaction.Isolation;
048    import com.liferay.portal.kernel.transaction.Propagation;
049    import com.liferay.portal.kernel.transaction.TransactionCommitCallbackUtil;
050    import com.liferay.portal.kernel.transaction.Transactional;
051    import com.liferay.portal.kernel.util.ListUtil;
052    import com.liferay.portal.model.impl.ResourceBlockImpl;
053    import com.liferay.portal.security.permission.PermissionCacheUtil;
054    import com.liferay.portal.service.base.ResourceBlockLocalServiceBaseImpl;
055    import com.liferay.portal.util.PropsValues;
056    import com.liferay.util.dao.orm.CustomSQLUtil;
057    
058    import java.sql.Connection;
059    import java.sql.SQLException;
060    
061    import java.util.ArrayList;
062    import java.util.List;
063    import java.util.Map;
064    import java.util.Set;
065    import java.util.concurrent.Callable;
066    
067    import javax.sql.DataSource;
068    
069    /**
070     * Provides the local service for accessing, adding, deleting, and updating
071     * resource blocks.
072     *
073     * @author Connor McKay
074     * @author Shuyang Zhou
075     */
076    public class ResourceBlockLocalServiceImpl
077            extends ResourceBlockLocalServiceBaseImpl {
078    
079            @Override
080            public void addCompanyScopePermission(
081                            long companyId, String name, long roleId, String actionId)
082                    throws PortalException {
083    
084                    updateCompanyScopePermissions(
085                            companyId, name, roleId, getActionId(name, actionId),
086                            ResourceBlockConstants.OPERATOR_ADD);
087            }
088    
089            @Override
090            public void addCompanyScopePermissions(
091                    long companyId, String name, long roleId, long actionIdsLong) {
092    
093                    updateCompanyScopePermissions(
094                            companyId, name, roleId, actionIdsLong,
095                            ResourceBlockConstants.OPERATOR_ADD);
096            }
097    
098            @Override
099            public void addGroupScopePermission(
100                            long companyId, long groupId, String name, long roleId,
101                            String actionId)
102                    throws PortalException {
103    
104                    updateGroupScopePermissions(
105                            companyId, groupId, name, roleId, getActionId(name, actionId),
106                            ResourceBlockConstants.OPERATOR_ADD);
107            }
108    
109            @Override
110            public void addGroupScopePermissions(
111                    long companyId, long groupId, String name, long roleId,
112                    long actionIdsLong) {
113    
114                    updateGroupScopePermissions(
115                            companyId, groupId, name, roleId, actionIdsLong,
116                            ResourceBlockConstants.OPERATOR_ADD);
117            }
118    
119            @Override
120            public void addIndividualScopePermission(
121                            long companyId, long groupId, String name, long primKey,
122                            long roleId, String actionId)
123                    throws PortalException {
124    
125                    PermissionedModel permissionedModel = getPermissionedModel(
126                            name, primKey);
127    
128                    updateIndividualScopePermissions(
129                            companyId, groupId, name, permissionedModel, roleId,
130                            getActionId(name, actionId), ResourceBlockConstants.OPERATOR_ADD);
131            }
132    
133            @Override
134            public void addIndividualScopePermission(
135                            long companyId, long groupId, String name,
136                            PermissionedModel permissionedModel, long roleId, String actionId)
137                    throws PortalException {
138    
139                    updateIndividualScopePermissions(
140                            companyId, groupId, name, permissionedModel, roleId,
141                            getActionId(name, actionId), ResourceBlockConstants.OPERATOR_ADD);
142            }
143    
144            @Override
145            public void addIndividualScopePermissions(
146                            long companyId, long groupId, String name, long primKey,
147                            long roleId, long actionIdsLong)
148                    throws PortalException {
149    
150                    PermissionedModel permissionedModel = getPermissionedModel(
151                            name, primKey);
152    
153                    updateIndividualScopePermissions(
154                            companyId, groupId, name, permissionedModel, roleId, actionIdsLong,
155                            ResourceBlockConstants.OPERATOR_ADD);
156            }
157    
158            @Override
159            public void addIndividualScopePermissions(
160                    long companyId, long groupId, String name,
161                    PermissionedModel permissionedModel, long roleId, long actionIdsLong) {
162    
163                    updateIndividualScopePermissions(
164                            companyId, groupId, name, permissionedModel, roleId, actionIdsLong,
165                            ResourceBlockConstants.OPERATOR_ADD);
166            }
167    
168            /**
169             * Adds a resource block if necessary and associates the resource block
170             * permissions with it. The resource block will have an initial reference
171             * count of one.
172             *
173             * @param  companyId the primary key of the resource block's company
174             * @param  groupId the primary key of the resource block's group
175             * @param  name the resource block's name
176             * @param  permissionsHash the resource block's permission hash
177             * @param  resourceBlockPermissionsContainer the resource block's
178             *         permissions container
179             * @return the new resource block
180             */
181            @Override
182            public ResourceBlock addResourceBlock(
183                    long companyId, long groupId, String name, String permissionsHash,
184                    ResourceBlockPermissionsContainer resourceBlockPermissionsContainer) {
185    
186                    long resourceBlockId = counterLocalService.increment(
187                            ResourceBlock.class.getName());
188    
189                    ResourceBlock resourceBlock = resourceBlockPersistence.create(
190                            resourceBlockId);
191    
192                    resourceBlock.setCompanyId(companyId);
193                    resourceBlock.setGroupId(groupId);
194                    resourceBlock.setName(name);
195                    resourceBlock.setPermissionsHash(permissionsHash);
196                    resourceBlock.setReferenceCount(1);
197    
198                    updateResourceBlock(resourceBlock);
199    
200                    resourceBlockPermissionLocalService.addResourceBlockPermissions(
201                            resourceBlockId, resourceBlockPermissionsContainer);
202    
203                    return resourceBlock;
204            }
205    
206            @Override
207            public ResourceBlock deleteResourceBlock(long resourceBlockId)
208                    throws PortalException {
209    
210                    ResourceBlock resourceBlock = resourceBlockPersistence.findByPrimaryKey(
211                            resourceBlockId);
212    
213                    return deleteResourceBlock(resourceBlock);
214            }
215    
216            @Override
217            public ResourceBlock deleteResourceBlock(ResourceBlock resourceBlock) {
218                    resourceBlockPermissionLocalService.deleteResourceBlockPermissions(
219                            resourceBlock.getPrimaryKey());
220    
221                    resourceBlockPersistence.remove(resourceBlock);
222    
223                    return resourceBlock;
224            }
225    
226            @Override
227            public long getActionId(String name, String actionId)
228                    throws PortalException {
229    
230                    ResourceAction resourcAction =
231                            resourceActionLocalService.getResourceAction(name, actionId);
232    
233                    return resourcAction.getBitwiseValue();
234            }
235    
236            @Override
237            public long getActionIds(String name, List<String> actionIds)
238                    throws PortalException {
239    
240                    long actionIdsLong = 0;
241    
242                    for (String actionId : actionIds) {
243                            ResourceAction resourceAction =
244                                    resourceActionLocalService.getResourceAction(name, actionId);
245    
246                            actionIdsLong |= resourceAction.getBitwiseValue();
247                    }
248    
249                    return actionIdsLong;
250            }
251    
252            @Override
253            public List<String> getActionIds(String name, long actionIdsLong) {
254                    List<ResourceAction> resourceActions =
255                            resourceActionLocalService.getResourceActions(name);
256    
257                    List<String> actionIds = new ArrayList<>();
258    
259                    for (ResourceAction resourceAction : resourceActions) {
260                            if ((actionIdsLong & resourceAction.getBitwiseValue()) ==
261                                            resourceAction.getBitwiseValue()) {
262    
263                                    actionIds.add(resourceAction.getActionId());
264                            }
265                    }
266    
267                    return actionIds;
268            }
269    
270            @Override
271            public List<String> getCompanyScopePermissions(
272                    ResourceBlock resourceBlock, long roleId) {
273    
274                    long actionIdsLong =
275                            resourceTypePermissionLocalService.getCompanyScopeActionIds(
276                                    resourceBlock.getCompanyId(), resourceBlock.getName(), roleId);
277    
278                    return getActionIds(resourceBlock.getName(), actionIdsLong);
279            }
280    
281            @Override
282            public List<String> getGroupScopePermissions(
283                    ResourceBlock resourceBlock, long roleId) {
284    
285                    long actionIdsLong =
286                            resourceTypePermissionLocalService.getGroupScopeActionIds(
287                                    resourceBlock.getCompanyId(), resourceBlock.getGroupId(),
288                                    resourceBlock.getName(), roleId);
289    
290                    return getActionIds(resourceBlock.getName(), actionIdsLong);
291            }
292    
293            @Override
294            public PermissionedModel getPermissionedModel(String name, long primKey)
295                    throws PortalException {
296    
297                    PersistedModelLocalService persistedModelLocalService =
298                            PersistedModelLocalServiceRegistryUtil.
299                                    getPersistedModelLocalService(name);
300    
301                    if (persistedModelLocalService == null) {
302                            throw new ResourceBlocksNotSupportedException();
303                    }
304    
305                    PersistedModel persistedModel =
306                            persistedModelLocalService.getPersistedModel(primKey);
307    
308                    try {
309                            return (PermissionedModel)persistedModel;
310                    }
311                    catch (ClassCastException cce) {
312                            throw new ResourceBlocksNotSupportedException();
313                    }
314            }
315    
316            @Override
317            public List<String> getPermissions(
318                    ResourceBlock resourceBlock, long roleId) {
319    
320                    ResourceBlockPermissionsContainer resourceBlockPermissionsContainer =
321                            resourceBlockPermissionLocalService.
322                                    getResourceBlockPermissionsContainer(
323                                            resourceBlock.getPrimaryKey());
324    
325                    long actionIdsLong = resourceBlockPermissionsContainer.getActionIds(
326                            roleId);
327    
328                    return getActionIds(resourceBlock.getName(), actionIdsLong);
329            }
330    
331            @Override
332            public ResourceBlock getResourceBlock(String name, long primKey)
333                    throws PortalException {
334    
335                    PermissionedModel permissionedModel = getPermissionedModel(
336                            name, primKey);
337    
338                    return getResourceBlock(permissionedModel.getResourceBlockId());
339            }
340    
341            @Override
342            public List<Long> getResourceBlockIds(
343                            ResourceBlockIdsBag resourceBlockIdsBag, String name,
344                            String actionId)
345                    throws PortalException {
346    
347                    long actionIdsLong = getActionId(name, actionId);
348    
349                    return resourceBlockIdsBag.getResourceBlockIds(actionIdsLong);
350            }
351    
352            @Override
353            public ResourceBlockIdsBag getResourceBlockIdsBag(
354                    long companyId, long groupId, String name, long[] roleIds) {
355    
356                    return resourceBlockFinder.findByC_G_N_R(
357                            companyId, groupId, name, roleIds);
358            }
359    
360            @Override
361            public List<Role> getRoles(String name, long primKey, String actionId)
362                    throws PortalException {
363    
364                    long actionIdLong = getActionId(name, actionId);
365    
366                    ResourceBlock resourceBlock = getResourceBlock(name, primKey);
367    
368                    ResourceBlockPermissionsContainer resourceBlockPermissionsContainer =
369                            resourceBlockPermissionLocalService.
370                                    getResourceBlockPermissionsContainer(
371                                            resourceBlock.getResourceBlockId());
372    
373                    Set<Long> roleIds = resourceBlockPermissionsContainer.getRoleIds();
374    
375                    List<Role> roles = new ArrayList<>(roleIds.size());
376    
377                    for (long roleId : roleIds) {
378                            if (resourceBlockPermissionsContainer.hasPermission(
379                                            roleId, actionIdLong)) {
380    
381                                    roles.add(roleLocalService.getRole(roleId));
382                            }
383                    }
384    
385                    return roles;
386            }
387    
388            @Override
389            public boolean hasPermission(
390                            String name, long primKey, String actionId,
391                            ResourceBlockIdsBag resourceBlockIdsBag)
392                    throws PortalException {
393    
394                    PermissionedModel permissionedModel = getPermissionedModel(
395                            name, primKey);
396    
397                    return hasPermission(
398                            name, permissionedModel, actionId, resourceBlockIdsBag);
399            }
400    
401            @Override
402            public boolean hasPermission(
403                            String name, PermissionedModel permissionedModel, String actionId,
404                            ResourceBlockIdsBag resourceBlockIdsBag)
405                    throws PortalException {
406    
407                    long actionIdsLong = getActionId(name, actionId);
408    
409                    return resourceBlockIdsBag.hasResourceBlockId(
410                            permissionedModel.getResourceBlockId(), actionIdsLong);
411            }
412    
413            @Override
414            public boolean isSupported(String name) {
415                    return PersistedModelLocalServiceRegistryUtil.
416                            isPermissionedModelLocalService(name);
417            }
418    
419            @Override
420            @Transactional(
421                    isolation = Isolation.READ_COMMITTED,
422                    propagation = Propagation.REQUIRES_NEW
423            )
424            public void releasePermissionedModelResourceBlock(
425                    PermissionedModel permissionedModel) {
426    
427                    releaseResourceBlock(permissionedModel.getResourceBlockId());
428            }
429    
430            @Override
431            public void releasePermissionedModelResourceBlock(String name, long primKey)
432                    throws PortalException {
433    
434                    PermissionedModel permissionedModel = getPermissionedModel(
435                            name, primKey);
436    
437                    releasePermissionedModelResourceBlock(permissionedModel);
438            }
439    
440            /**
441             * Decrements the reference count of the resource block and updates it in
442             * the database or deletes the resource block if the reference count reaches
443             * zero.
444             *
445             * @param resourceBlockId the primary key of the resource block
446             */
447            @Override
448            @Transactional(
449                    isolation = Isolation.READ_COMMITTED,
450                    propagation = Propagation.REQUIRES_NEW
451            )
452            public void releaseResourceBlock(long resourceBlockId) {
453                    Session session = resourceBlockPersistence.openSession();
454    
455                    while (true) {
456                            try {
457                                    String sql = CustomSQLUtil.get(_RELEASE_RESOURCE_BLOCK);
458    
459                                    SQLQuery sqlQuery = session.createSynchronizedSQLQuery(sql);
460    
461                                    QueryPos qPos = QueryPos.getInstance(sqlQuery);
462    
463                                    qPos.add(resourceBlockId);
464    
465                                    if (sqlQuery.executeUpdate() > 0) {
466                                            ResourceBlock resourceBlock = (ResourceBlock)session.get(
467                                                    ResourceBlockImpl.class, Long.valueOf(resourceBlockId));
468    
469                                            if (resourceBlock.getReferenceCount() == 0) {
470                                                    sql = CustomSQLUtil.get(_DELETE_RESOURCE_BLOCK);
471    
472                                                    sqlQuery = session.createSynchronizedSQLQuery(sql);
473    
474                                                    qPos = QueryPos.getInstance(sqlQuery);
475    
476                                                    qPos.add(resourceBlockId);
477    
478                                                    sqlQuery.executeUpdate();
479    
480                                                    PermissionCacheUtil.clearResourceBlockCache(
481                                                            resourceBlock.getCompanyId(),
482                                                            resourceBlock.getGroupId(),
483                                                            resourceBlock.getName());
484                                            }
485                                    }
486    
487                                    resourceBlockPersistence.closeSession(session);
488    
489                                    break;
490                            }
491                            catch (ORMException orme) {
492                                    if (_log.isWarnEnabled()) {
493                                            _log.warn(
494                                                    "Unable to decrement reference count for resource " +
495                                                            "block " + resourceBlockId + ". Retrying.");
496                                    }
497                            }
498                    }
499            }
500    
501            /**
502             * Decrements the reference count of the resource block and updates it in
503             * the database or deletes the resource block if the reference count reaches
504             * zero.
505             *
506             * @param resourceBlock the resource block
507             */
508            @Override
509            @Transactional(
510                    isolation = Isolation.READ_COMMITTED,
511                    propagation = Propagation.REQUIRES_NEW
512            )
513            public void releaseResourceBlock(ResourceBlock resourceBlock) {
514                    releaseResourceBlock(resourceBlock.getResourceBlockId());
515            }
516    
517            @Override
518            public void removeAllGroupScopePermissions(
519                    long companyId, String name, long roleId, long actionIdsLong) {
520    
521                    List<ResourceTypePermission> resourceTypePermissions =
522                            resourceTypePermissionLocalService.
523                                    getGroupScopeResourceTypePermissions(companyId, name, roleId);
524    
525                    for (ResourceTypePermission resourceTypePermission :
526                                    resourceTypePermissions) {
527    
528                            removeGroupScopePermissions(
529                                    companyId, resourceTypePermission.getGroupId(), name, roleId,
530                                    actionIdsLong);
531                    }
532            }
533    
534            @Override
535            public void removeAllGroupScopePermissions(
536                            long companyId, String name, long roleId, String actionId)
537                    throws PortalException {
538    
539                    removeAllGroupScopePermissions(
540                            companyId, name, roleId, getActionId(name, actionId));
541            }
542    
543            @Override
544            public void removeCompanyScopePermission(
545                            long companyId, String name, long roleId, String actionId)
546                    throws PortalException {
547    
548                    updateCompanyScopePermissions(
549                            companyId, name, roleId, getActionId(name, actionId),
550                            ResourceBlockConstants.OPERATOR_REMOVE);
551            }
552    
553            @Override
554            public void removeCompanyScopePermissions(
555                    long companyId, String name, long roleId, long actionIdsLong) {
556    
557                    updateCompanyScopePermissions(
558                            companyId, name, roleId, actionIdsLong,
559                            ResourceBlockConstants.OPERATOR_REMOVE);
560            }
561    
562            @Override
563            public void removeGroupScopePermission(
564                            long companyId, long groupId, String name, long roleId,
565                            String actionId)
566                    throws PortalException {
567    
568                    updateGroupScopePermissions(
569                            companyId, groupId, name, roleId, getActionId(name, actionId),
570                            ResourceBlockConstants.OPERATOR_REMOVE);
571            }
572    
573            @Override
574            public void removeGroupScopePermissions(
575                    long companyId, long groupId, String name, long roleId,
576                    long actionIdsLong) {
577    
578                    updateGroupScopePermissions(
579                            companyId, groupId, name, roleId, actionIdsLong,
580                            ResourceBlockConstants.OPERATOR_REMOVE);
581            }
582    
583            @Override
584            public void removeIndividualScopePermission(
585                            long companyId, long groupId, String name, long primKey,
586                            long roleId, String actionId)
587                    throws PortalException {
588    
589                    PermissionedModel permissionedModel = getPermissionedModel(
590                            name, primKey);
591    
592                    updateIndividualScopePermissions(
593                            companyId, groupId, name, permissionedModel, roleId,
594                            getActionId(name, actionId),
595                            ResourceBlockConstants.OPERATOR_REMOVE);
596            }
597    
598            @Override
599            public void removeIndividualScopePermission(
600                            long companyId, long groupId, String name,
601                            PermissionedModel permissionedModel, long roleId, String actionId)
602                    throws PortalException {
603    
604                    updateIndividualScopePermissions(
605                            companyId, groupId, name, permissionedModel, roleId,
606                            getActionId(name, actionId),
607                            ResourceBlockConstants.OPERATOR_REMOVE);
608            }
609    
610            @Override
611            public void removeIndividualScopePermissions(
612                            long companyId, long groupId, String name, long primKey,
613                            long roleId, long actionIdsLong)
614                    throws PortalException {
615    
616                    PermissionedModel permissionedModel = getPermissionedModel(
617                            name, primKey);
618    
619                    updateIndividualScopePermissions(
620                            companyId, groupId, name, permissionedModel, roleId, actionIdsLong,
621                            ResourceBlockConstants.OPERATOR_REMOVE);
622            }
623    
624            @Override
625            public void removeIndividualScopePermissions(
626                    long companyId, long groupId, String name,
627                    PermissionedModel permissionedModel, long roleId, long actionIdsLong) {
628    
629                    updateIndividualScopePermissions(
630                            companyId, groupId, name, permissionedModel, roleId, actionIdsLong,
631                            ResourceBlockConstants.OPERATOR_REMOVE);
632            }
633    
634            @Override
635            public void setCompanyScopePermissions(
636                            long companyId, String name, long roleId, List<String> actionIds)
637                    throws PortalException {
638    
639                    checkGuestSupportedPermission(companyId, name, roleId, actionIds);
640    
641                    updateCompanyScopePermissions(
642                            companyId, name, roleId, getActionIds(name, actionIds),
643                            ResourceBlockConstants.OPERATOR_SET);
644            }
645    
646            @Override
647            public void setCompanyScopePermissions(
648                    long companyId, String name, long roleId, long actionIdsLong) {
649    
650                    updateCompanyScopePermissions(
651                            companyId, name, roleId, actionIdsLong,
652                            ResourceBlockConstants.OPERATOR_SET);
653            }
654    
655            @Override
656            public void setGroupScopePermissions(
657                            long companyId, long groupId, String name, long roleId,
658                            List<String> actionIds)
659                    throws PortalException {
660    
661                    checkGuestSupportedPermission(companyId, name, roleId, actionIds);
662    
663                    updateGroupScopePermissions(
664                            companyId, groupId, name, roleId, getActionIds(name, actionIds),
665                            ResourceBlockConstants.OPERATOR_SET);
666            }
667    
668            @Override
669            public void setGroupScopePermissions(
670                    long companyId, long groupId, String name, long roleId,
671                    long actionIdsLong) {
672    
673                    updateGroupScopePermissions(
674                            companyId, groupId, name, roleId, actionIdsLong,
675                            ResourceBlockConstants.OPERATOR_SET);
676            }
677    
678            @Override
679            public void setIndividualScopePermissions(
680                            long companyId, long groupId, String name, long primKey,
681                            long roleId, List<String> actionIds)
682                    throws PortalException {
683    
684                    PermissionedModel permissionedModel = getPermissionedModel(
685                            name, primKey);
686    
687                    checkGuestSupportedPermission(companyId, name, roleId, actionIds);
688    
689                    updateIndividualScopePermissions(
690                            companyId, groupId, name, permissionedModel, roleId,
691                            getActionIds(name, actionIds), ResourceBlockConstants.OPERATOR_SET);
692            }
693    
694            @Override
695            public void setIndividualScopePermissions(
696                            long companyId, long groupId, String name, long primKey,
697                            long roleId, long actionIdsLong)
698                    throws PortalException {
699    
700                    PermissionedModel permissionedModel = getPermissionedModel(
701                            name, primKey);
702    
703                    updateIndividualScopePermissions(
704                            companyId, groupId, name, permissionedModel, roleId, actionIdsLong,
705                            ResourceBlockConstants.OPERATOR_SET);
706            }
707    
708            @Override
709            public void setIndividualScopePermissions(
710                            long companyId, long groupId, String name, long primKey,
711                            Map<Long, String[]> roleIdsToActionIds)
712                    throws PortalException {
713    
714                    boolean flushResourceBlockEnabled =
715                            PermissionThreadLocal.isFlushResourceBlockEnabled(
716                                    companyId, groupId, name);
717    
718                    PermissionThreadLocal.setFlushResourceBlockEnabled(
719                            companyId, groupId, name, false);
720    
721                    try {
722                            PermissionedModel permissionedModel = getPermissionedModel(
723                                    name, primKey);
724    
725                            for (Map.Entry<Long, String[]> entry :
726                                            roleIdsToActionIds.entrySet()) {
727    
728                                    long roleId = entry.getKey();
729                                    List<String> actionIds = ListUtil.fromArray(entry.getValue());
730    
731                                    checkGuestSupportedPermission(
732                                            companyId, name, roleId, actionIds);
733    
734                                    updateIndividualScopePermissions(
735                                            companyId, groupId, name, permissionedModel, roleId,
736                                            getActionIds(name, actionIds),
737                                            ResourceBlockConstants.OPERATOR_SET);
738                            }
739                    }
740                    finally {
741                            PermissionThreadLocal.setFlushResourceBlockEnabled(
742                                    companyId, groupId, name, flushResourceBlockEnabled);
743    
744                            PermissionCacheUtil.clearResourceBlockCache(
745                                    companyId, groupId, name);
746    
747                            PermissionCacheUtil.clearResourcePermissionCache(
748                                    ResourceConstants.SCOPE_INDIVIDUAL, name,
749                                    String.valueOf(primKey));
750                    }
751            }
752    
753            @Override
754            public void setIndividualScopePermissions(
755                            long companyId, long groupId, String name,
756                            PermissionedModel permissionedModel, long roleId,
757                            List<String> actionIds)
758                    throws PortalException {
759    
760                    checkGuestSupportedPermission(companyId, name, roleId, actionIds);
761    
762                    updateIndividualScopePermissions(
763                            companyId, groupId, name, permissionedModel, roleId,
764                            getActionIds(name, actionIds), ResourceBlockConstants.OPERATOR_SET);
765            }
766    
767            @Override
768            public void setIndividualScopePermissions(
769                    long companyId, long groupId, String name,
770                    PermissionedModel permissionedModel, long roleId, long actionIdsLong) {
771    
772                    updateIndividualScopePermissions(
773                            companyId, groupId, name, permissionedModel, roleId, actionIdsLong,
774                            ResourceBlockConstants.OPERATOR_SET);
775            }
776    
777            @Override
778            public void updateCompanyScopePermissions(
779                    long companyId, String name, long roleId, long actionIdsLong,
780                    int operator) {
781    
782                    resourceTypePermissionLocalService.
783                            updateCompanyScopeResourceTypePermissions(
784                                    companyId, name, roleId, actionIdsLong, operator);
785    
786                    List<ResourceBlock> resourceBlocks = resourceBlockPersistence.findByC_N(
787                            companyId, name);
788    
789                    updatePermissions(resourceBlocks, roleId, actionIdsLong, operator);
790    
791                    PermissionCacheUtil.clearResourceCache();
792            }
793    
794            @Override
795            public void updateGroupScopePermissions(
796                    long companyId, long groupId, String name, long roleId,
797                    long actionIdsLong, int operator) {
798    
799                    resourceTypePermissionLocalService.
800                            updateGroupScopeResourceTypePermissions(
801                                    companyId, groupId, name, roleId, actionIdsLong, operator);
802    
803                    List<ResourceBlock> resourceBlocks =
804                            resourceBlockPersistence.findByC_G_N(companyId, groupId, name);
805    
806                    updatePermissions(resourceBlocks, roleId, actionIdsLong, operator);
807    
808                    PermissionCacheUtil.clearResourceCache();
809            }
810    
811            @Override
812            public void updateIndividualScopePermissions(
813                    long companyId, long groupId, String name,
814                    PermissionedModel permissionedModel, long roleId, long actionIdsLong,
815                    int operator) {
816    
817                    ResourceBlock resourceBlock =
818                            resourceBlockPersistence.fetchByPrimaryKey(
819                                    permissionedModel.getResourceBlockId());
820    
821                    ResourceBlockPermissionsContainer resourceBlockPermissionsContainer =
822                            null;
823    
824                    if (resourceBlock == null) {
825                            resourceBlockPermissionsContainer =
826                                    resourceTypePermissionLocalService.
827                                            getResourceBlockPermissionsContainer(
828                                                    companyId, groupId, name);
829                    }
830                    else {
831                            resourceBlockPermissionsContainer =
832                                    resourceBlockPermissionLocalService.
833                                            getResourceBlockPermissionsContainer(
834                                                    resourceBlock.getPrimaryKey());
835                    }
836    
837                    long oldActionIdsLong = resourceBlockPermissionsContainer.getActionIds(
838                            roleId);
839    
840                    if (operator == ResourceBlockConstants.OPERATOR_ADD) {
841                            actionIdsLong |= oldActionIdsLong;
842                    }
843                    else if (operator == ResourceBlockConstants.OPERATOR_REMOVE) {
844                            actionIdsLong = oldActionIdsLong & (~actionIdsLong);
845                    }
846    
847                    if (resourceBlock != null) {
848                            if (oldActionIdsLong == actionIdsLong) {
849                                    return;
850                            }
851    
852                            resourceBlockLocalService.releaseResourceBlock(resourceBlock);
853                    }
854    
855                    resourceBlockPermissionsContainer.setPermissions(roleId, actionIdsLong);
856    
857                    String permissionsHash =
858                            resourceBlockPermissionsContainer.getPermissionsHash();
859    
860                    resourceBlockLocalService.updateResourceBlockId(
861                            companyId, groupId, name, permissionedModel, permissionsHash,
862                            resourceBlockPermissionsContainer);
863    
864                    PermissionCacheUtil.clearResourceBlockCache(companyId, groupId, name);
865            }
866    
867            @Override
868            @Transactional(
869                    isolation = Isolation.READ_COMMITTED,
870                    propagation = Propagation.REQUIRES_NEW
871            )
872            public ResourceBlock updateResourceBlockId(
873                    long companyId, long groupId, String name,
874                    final PermissionedModel permissionedModel, String permissionsHash,
875                    ResourceBlockPermissionsContainer resourceBlockPermissionsContainer) {
876    
877                    ResourceBlock resourceBlock = null;
878    
879                    while (true) {
880                            resourceBlock = resourceBlockPersistence.fetchByC_G_N_P(
881                                    companyId, groupId, name, permissionsHash, false);
882    
883                            if (resourceBlock == null) {
884                                    try {
885                                            resourceBlock = addResourceBlock(
886                                                    companyId, groupId, name, permissionsHash,
887                                                    resourceBlockPermissionsContainer);
888    
889                                            // On success, manually flush to enforce database row lock
890    
891                                            if (PropsValues.SPRING_HIBERNATE_SESSION_DELEGATED) {
892                                                    resourceBlockPersistence.flush();
893                                            }
894                                    }
895                                    catch (SystemException se) {
896                                            if (_log.isWarnEnabled()) {
897                                                    _log.warn(
898                                                            "Unable to add a new resource block. Retrying");
899                                            }
900    
901                                            // On failure, cancel all pending persistent entities
902    
903                                            Session session =
904                                                    resourceBlockPersistence.getCurrentSession();
905    
906                                            session.clear();
907    
908                                            DB db = DBManagerUtil.getDB();
909    
910                                            if (!db.isSupportsQueryingAfterException()) {
911                                                    DataSource dataSource =
912                                                            resourceBlockPersistence.getDataSource();
913    
914                                                    Connection connection =
915                                                            CurrentConnectionUtil.getConnection(dataSource);
916    
917                                                    try {
918                                                            connection.rollback();
919    
920                                                            connection.setAutoCommit(false);
921                                                    }
922                                                    catch (SQLException sqle) {
923                                                            throw new SystemException(sqle);
924                                                    }
925                                            }
926    
927                                            continue;
928                                    }
929    
930                                    break;
931                            }
932    
933                            Session session = resourceBlockPersistence.openSession();
934    
935                            try {
936                                    String sql = CustomSQLUtil.get(_RETAIN_RESOURCE_BLOCK);
937    
938                                    SQLQuery sqlQuery = session.createSynchronizedSQLQuery(sql);
939    
940                                    QueryPos qPos = QueryPos.getInstance(sqlQuery);
941    
942                                    qPos.add(resourceBlock.getResourceBlockId());
943    
944                                    if (sqlQuery.executeUpdate() > 0) {
945    
946                                            // We currently use an "update set" SQL statement to
947                                            // increment the reference count in a discontinuous manner.
948                                            // We can change it to an "update where" SQL statement to
949                                            // guarantee continuous counts. We are using a SQL statement
950                                            // that allows for a discontinuous count since it is cheaper
951                                            // and continuity is not required.
952    
953                                            resourceBlock.setReferenceCount(
954                                                    resourceBlock.getReferenceCount() + 1);
955    
956                                            break;
957                                    }
958                            }
959                            catch (ORMException orme) {
960                                    if (_log.isWarnEnabled()) {
961                                            _log.warn(
962                                                    "Unable to increment reference count for resource " +
963                                                            "block " + resourceBlock.getResourceBlockId() +
964                                                                    ". Retrying");
965                                    }
966                            }
967                            finally {
968    
969                                    // Prevent Hibernate from automatically flushing out the first
970                                    // level cache since that will lead to a regular update that
971                                    // will overwrite the previous update causing a lost update.
972    
973                                    session.evict(resourceBlock);
974    
975                                    resourceBlockPersistence.closeSession(session);
976                            }
977                    }
978    
979                    permissionedModel.setResourceBlockId(
980                            resourceBlock.getResourceBlockId());
981    
982                    Callable<Void> callable = new Callable<Void>() {
983    
984                            @Override
985                            public Void call() throws Exception {
986                                    permissionedModel.persist();
987    
988                                    return null;
989                            }
990    
991                    };
992    
993                    TransactionCommitCallbackUtil.registerCallback(callable);
994    
995                    return resourceBlock;
996            }
997    
998            @Override
999            public void verifyResourceBlockId(long companyId, String name, long primKey)
1000                    throws PortalException {
1001    
1002                    PermissionedModel permissionedModel = getPermissionedModel(
1003                            name, primKey);
1004    
1005                    ResourceBlock resourceBlock =
1006                            resourceBlockPersistence.fetchByPrimaryKey(
1007                                    permissionedModel.getResourceBlockId());
1008    
1009                    if (resourceBlock != null) {
1010                            return;
1011                    }
1012    
1013                    if (_log.isWarnEnabled()) {
1014                            _log.warn(
1015                                    "Resource block " + permissionedModel.getResourceBlockId() +
1016                                            " missing for " + name + "#" + primKey);
1017                    }
1018    
1019                    long groupId = 0;
1020                    long ownerId = 0;
1021    
1022                    if (permissionedModel instanceof GroupedModel) {
1023                            GroupedModel groupedModel = (GroupedModel)permissionedModel;
1024    
1025                            groupId = groupedModel.getGroupId();
1026                            ownerId = groupedModel.getUserId();
1027                    }
1028                    else if (permissionedModel instanceof AuditedModel) {
1029                            AuditedModel auditedModel = (AuditedModel)permissionedModel;
1030    
1031                            ownerId = auditedModel.getUserId();
1032                    }
1033    
1034                    resourceLocalService.addResources(
1035                            companyId, groupId, ownerId, name, primKey, false, true, true);
1036            }
1037    
1038            protected void checkGuestSupportedPermission(
1039                            long companyId, String name, long roleId, List<String> actionIds)
1040                    throws PortalException {
1041    
1042                    if (!isGuestRole(companyId, roleId)) {
1043                            return;
1044                    }
1045    
1046                    List<String> unsupportedActionIds =
1047                            ResourceActionsUtil.getResourceGuestUnsupportedActions(name, name);
1048    
1049                    for (String actionId : actionIds) {
1050                            if (unsupportedActionIds.contains(actionId)) {
1051                                    throw new PrincipalException(
1052                                            actionId + "is not supported by role " + roleId);
1053                            }
1054                    }
1055            }
1056    
1057            protected boolean isGuestRole(long companyId, long roleId)
1058                    throws PortalException {
1059    
1060                    Role guestRole = roleLocalService.getRole(
1061                            companyId, RoleConstants.GUEST);
1062    
1063                    if (roleId == guestRole.getRoleId()) {
1064                            return true;
1065                    }
1066    
1067                    return false;
1068            }
1069    
1070            protected void updatePermissions(
1071                    List<ResourceBlock> resourceBlocks, long roleId, long actionIdsLong,
1072                    int operator) {
1073    
1074                    for (ResourceBlock resourceBlock : resourceBlocks) {
1075                            resourceBlockPermissionLocalService.updateResourceBlockPermission(
1076                                    resourceBlock.getPrimaryKey(), roleId, actionIdsLong, operator);
1077    
1078                            updatePermissionsHash(resourceBlock);
1079                    }
1080            }
1081    
1082            protected void updatePermissionsHash(ResourceBlock resourceBlock) {
1083                    ResourceBlockPermissionsContainer resourceBlockPermissionsContainer =
1084                            resourceBlockPermissionLocalService.
1085                                    getResourceBlockPermissionsContainer(
1086                                            resourceBlock.getPrimaryKey());
1087    
1088                    String permissionsHash =
1089                            resourceBlockPermissionsContainer.getPermissionsHash();
1090    
1091                    resourceBlock.setPermissionsHash(permissionsHash);
1092    
1093                    updateResourceBlock(resourceBlock);
1094            }
1095    
1096            private static final String _DELETE_RESOURCE_BLOCK =
1097                    ResourceBlockLocalServiceImpl.class.getName() + ".deleteResourceBlock";
1098    
1099            private static final String _RELEASE_RESOURCE_BLOCK =
1100                    ResourceBlockLocalServiceImpl.class.getName() + ".releaseResourceBlock";
1101    
1102            private static final String _RETAIN_RESOURCE_BLOCK =
1103                    ResourceBlockLocalServiceImpl.class.getName() + ".retainResourceBlock";
1104    
1105            private static final Log _log = LogFactoryUtil.getLog(
1106                    ResourceBlockLocalServiceImpl.class);
1107    
1108    }