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