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