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