001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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, SystemException {
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                    throws SystemException {
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, SystemException {
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                    throws SystemException {
113    
114                    updateGroupScopePermissions(
115                            companyId, groupId, name, roleId, actionIdsLong,
116                            ResourceBlockConstants.OPERATOR_ADD);
117            }
118    
119            @Override
120            public void addIndividualScopePermission(
121                            long companyId, long groupId, String name, long primKey,
122                            long roleId, String actionId)
123                    throws PortalException, SystemException {
124    
125                    PermissionedModel permissionedModel = getPermissionedModel(
126                            name, primKey);
127    
128                    updateIndividualScopePermissions(
129                            companyId, groupId, name, permissionedModel, roleId,
130                            getActionId(name, actionId), ResourceBlockConstants.OPERATOR_ADD);
131            }
132    
133            @Override
134            public void addIndividualScopePermission(
135                            long companyId, long groupId, String name,
136                            PermissionedModel permissionedModel, long roleId, String actionId)
137                    throws PortalException, SystemException {
138    
139                    updateIndividualScopePermissions(
140                            companyId, groupId, name, permissionedModel, roleId,
141                            getActionId(name, actionId), ResourceBlockConstants.OPERATOR_ADD);
142            }
143    
144            @Override
145            public void addIndividualScopePermissions(
146                            long companyId, long groupId, String name, long primKey,
147                            long roleId, long actionIdsLong)
148                    throws PortalException, SystemException {
149    
150                    PermissionedModel permissionedModel = getPermissionedModel(
151                            name, primKey);
152    
153                    updateIndividualScopePermissions(
154                            companyId, groupId, name, permissionedModel, roleId, actionIdsLong,
155                            ResourceBlockConstants.OPERATOR_ADD);
156            }
157    
158            @Override
159            public void addIndividualScopePermissions(
160                            long companyId, long groupId, String name,
161                            PermissionedModel permissionedModel, long roleId,
162                            long actionIdsLong)
163                    throws SystemException {
164    
165                    updateIndividualScopePermissions(
166                            companyId, groupId, name, permissionedModel, roleId, actionIdsLong,
167                            ResourceBlockConstants.OPERATOR_ADD);
168            }
169    
170            /**
171             * Adds a resource block if necessary and associates the resource block
172             * permissions with it. The resource block will have an initial reference
173             * count of one.
174             *
175             * @param  companyId the primary key of the resource block's company
176             * @param  groupId the primary key of the resource block's group
177             * @param  name the resource block's name
178             * @param  permissionsHash the resource block's permission hash
179             * @param  resourceBlockPermissionsContainer the resource block's
180             *         permissions container
181             * @return the new resource block
182             * @throws SystemException if a system exception occurred
183             */
184            @Override
185            public ResourceBlock addResourceBlock(
186                            long companyId, long groupId, String name, String permissionsHash,
187                            ResourceBlockPermissionsContainer resourceBlockPermissionsContainer)
188                    throws SystemException {
189    
190                    long resourceBlockId = counterLocalService.increment(
191                            ResourceBlock.class.getName());
192    
193                    ResourceBlock resourceBlock = resourceBlockPersistence.create(
194                            resourceBlockId);
195    
196                    resourceBlock.setCompanyId(companyId);
197                    resourceBlock.setGroupId(groupId);
198                    resourceBlock.setName(name);
199                    resourceBlock.setPermissionsHash(permissionsHash);
200                    resourceBlock.setReferenceCount(1);
201    
202                    updateResourceBlock(resourceBlock);
203    
204                    resourceBlockPermissionLocalService.addResourceBlockPermissions(
205                            resourceBlockId, resourceBlockPermissionsContainer);
206    
207                    return resourceBlock;
208            }
209    
210            @Override
211            public ResourceBlock deleteResourceBlock(long resourceBlockId)
212                    throws PortalException, SystemException {
213    
214                    ResourceBlock resourceBlock = resourceBlockPersistence.findByPrimaryKey(
215                            resourceBlockId);
216    
217                    return deleteResourceBlock(resourceBlock);
218            }
219    
220            @Override
221            public ResourceBlock deleteResourceBlock(ResourceBlock resourceBlock)
222                    throws SystemException {
223    
224                    resourceBlockPermissionLocalService.deleteResourceBlockPermissions(
225                            resourceBlock.getPrimaryKey());
226    
227                    resourceBlockPersistence.remove(resourceBlock);
228    
229                    return resourceBlock;
230            }
231    
232            @Override
233            public long getActionId(String name, String actionId)
234                    throws PortalException {
235    
236                    ResourceAction resourcAction =
237                            resourceActionLocalService.getResourceAction(name, actionId);
238    
239                    return resourcAction.getBitwiseValue();
240            }
241    
242            @Override
243            public long getActionIds(String name, List<String> actionIds)
244                    throws PortalException {
245    
246                    long actionIdsLong = 0;
247    
248                    for (String actionId : actionIds) {
249                            ResourceAction resourceAction =
250                                    resourceActionLocalService.getResourceAction(name, actionId);
251    
252                            actionIdsLong |= resourceAction.getBitwiseValue();
253                    }
254    
255                    return actionIdsLong;
256            }
257    
258            @Override
259            public List<String> getActionIds(String name, long actionIdsLong)
260                    throws SystemException {
261    
262                    List<ResourceAction> resourceActions =
263                            resourceActionLocalService.getResourceActions(name);
264    
265                    List<String> actionIds = new ArrayList<String>();
266    
267                    for (ResourceAction resourceAction : resourceActions) {
268                            if ((actionIdsLong & resourceAction.getBitwiseValue()) ==
269                                            resourceAction.getBitwiseValue()) {
270    
271                                    actionIds.add(resourceAction.getActionId());
272                            }
273                    }
274    
275                    return actionIds;
276            }
277    
278            @Override
279            public List<String> getCompanyScopePermissions(
280                            ResourceBlock resourceBlock, long roleId)
281                    throws SystemException {
282    
283                    long actionIdsLong =
284                            resourceTypePermissionLocalService.getCompanyScopeActionIds(
285                                    resourceBlock.getCompanyId(), resourceBlock.getName(), roleId);
286    
287                    return getActionIds(resourceBlock.getName(), actionIdsLong);
288            }
289    
290            @Override
291            public List<String> getGroupScopePermissions(
292                            ResourceBlock resourceBlock, long roleId)
293                    throws SystemException {
294    
295                    long actionIdsLong =
296                            resourceTypePermissionLocalService.getGroupScopeActionIds(
297                                    resourceBlock.getCompanyId(), resourceBlock.getGroupId(),
298                                    resourceBlock.getName(), roleId);
299    
300                    return getActionIds(resourceBlock.getName(), actionIdsLong);
301            }
302    
303            @Override
304            public PermissionedModel getPermissionedModel(String name, long primKey)
305                    throws PortalException, SystemException {
306    
307                    PersistedModelLocalService persistedModelLocalService =
308                            PersistedModelLocalServiceRegistryUtil.
309                                    getPersistedModelLocalService(name);
310    
311                    if (persistedModelLocalService == null) {
312                            throw new ResourceBlocksNotSupportedException();
313                    }
314    
315                    PersistedModel persistedModel =
316                            persistedModelLocalService.getPersistedModel(primKey);
317    
318                    try {
319                            return (PermissionedModel)persistedModel;
320                    }
321                    catch (ClassCastException cce) {
322                            throw new ResourceBlocksNotSupportedException();
323                    }
324            }
325    
326            @Override
327            public List<String> getPermissions(ResourceBlock resourceBlock, long roleId)
328                    throws SystemException {
329    
330                    ResourceBlockPermissionsContainer resourceBlockPermissionsContainer =
331                            resourceBlockPermissionLocalService.
332                                    getResourceBlockPermissionsContainer(
333                                            resourceBlock.getPrimaryKey());
334    
335                    long actionIdsLong = resourceBlockPermissionsContainer.getActionIds(
336                            roleId);
337    
338                    return getActionIds(resourceBlock.getName(), actionIdsLong);
339            }
340    
341            @Override
342            public ResourceBlock getResourceBlock(String name, long primKey)
343                    throws PortalException, SystemException {
344    
345                    PermissionedModel permissionedModel = getPermissionedModel(
346                            name, primKey);
347    
348                    return getResourceBlock(permissionedModel.getResourceBlockId());
349            }
350    
351            @Override
352            public List<Long> getResourceBlockIds(
353                            ResourceBlockIdsBag resourceBlockIdsBag, String name,
354                            String actionId)
355                    throws PortalException {
356    
357                    long actionIdsLong = getActionId(name, actionId);
358    
359                    return resourceBlockIdsBag.getResourceBlockIds(actionIdsLong);
360            }
361    
362            @Override
363            public ResourceBlockIdsBag getResourceBlockIdsBag(
364                            long companyId, long groupId, String name, long[] roleIds)
365                    throws SystemException {
366    
367                    return resourceBlockFinder.findByC_G_N_R(
368                            companyId, groupId, name, roleIds);
369            }
370    
371            @Override
372            public boolean hasPermission(
373                            String name, long primKey, String actionId,
374                            ResourceBlockIdsBag resourceBlockIdsBag)
375                    throws PortalException, SystemException {
376    
377                    PermissionedModel permissionedModel = getPermissionedModel(
378                            name, primKey);
379    
380                    return hasPermission(
381                            name, permissionedModel, actionId, resourceBlockIdsBag);
382            }
383    
384            @Override
385            public boolean hasPermission(
386                            String name, PermissionedModel permissionedModel, String actionId,
387                            ResourceBlockIdsBag resourceBlockIdsBag)
388                    throws PortalException {
389    
390                    long actionIdsLong = getActionId(name, actionId);
391    
392                    return resourceBlockIdsBag.hasResourceBlockId(
393                            permissionedModel.getResourceBlockId(), actionIdsLong);
394            }
395    
396            @Override
397            public boolean isSupported(String name) {
398                    return PersistedModelLocalServiceRegistryUtil.
399                            isPermissionedModelLocalService(name);
400            }
401    
402            @Override
403            @Transactional(
404                    isolation = Isolation.READ_COMMITTED,
405                    propagation = Propagation.REQUIRES_NEW)
406            public void releasePermissionedModelResourceBlock(
407                            PermissionedModel permissionedModel)
408                    throws SystemException {
409    
410                    releaseResourceBlock(permissionedModel.getResourceBlockId());
411            }
412    
413            @Override
414            public void releasePermissionedModelResourceBlock(String name, long primKey)
415                    throws PortalException, SystemException {
416    
417                    PermissionedModel permissionedModel = getPermissionedModel(
418                            name, primKey);
419    
420                    releasePermissionedModelResourceBlock(permissionedModel);
421            }
422    
423            /**
424             * Decrements the reference count of the resource block and updates it in
425             * the database or deletes the resource block if the reference count reaches
426             * zero.
427             *
428             * @param  resourceBlockId the primary key of the resource block
429             * @throws SystemException if a system exception occurred
430             */
431            @Override
432            @Transactional(
433                    isolation = Isolation.READ_COMMITTED,
434                    propagation = Propagation.REQUIRES_NEW)
435            public void releaseResourceBlock(long resourceBlockId)
436                    throws SystemException {
437    
438                    Session session = resourceBlockPersistence.openSession();
439    
440                    while (true) {
441                            try {
442                                    String sql = CustomSQLUtil.get(_RELEASE_RESOURCE_BLOCK);
443    
444                                    SQLQuery sqlQuery = session.createSQLQuery(sql);
445    
446                                    QueryPos qPos = QueryPos.getInstance(sqlQuery);
447    
448                                    qPos.add(resourceBlockId);
449    
450                                    if (sqlQuery.executeUpdate() > 0) {
451                                            ResourceBlock resourceBlock = (ResourceBlock)session.get(
452                                                    ResourceBlockImpl.class, Long.valueOf(resourceBlockId));
453    
454                                            if (resourceBlock.getReferenceCount() == 0) {
455                                                    sql = CustomSQLUtil.get(_DELETE_RESOURCE_BLOCK);
456    
457                                                    sqlQuery = session.createSQLQuery(sql);
458    
459                                                    qPos = QueryPos.getInstance(sqlQuery);
460    
461                                                    qPos.add(resourceBlockId);
462    
463                                                    sqlQuery.executeUpdate();
464    
465                                                    PermissionCacheUtil.clearResourceBlockCache(
466                                                            resourceBlock.getCompanyId(),
467                                                            resourceBlock.getGroupId(),
468                                                            resourceBlock.getName());
469                                            }
470                                    }
471    
472                                    resourceBlockPersistence.closeSession(session);
473    
474                                    break;
475                            }
476                            catch (ORMException orme) {
477                                    if (_log.isWarnEnabled()) {
478                                            _log.warn(
479                                                    "Unable to decrement reference count for resource " +
480                                                            "block " + resourceBlockId + ". Retrying.");
481                                    }
482                            }
483                    }
484            }
485    
486            /**
487             * Decrements the reference count of the resource block and updates it in
488             * the database or deletes the resource block if the reference count reaches
489             * zero.
490             *
491             * @param  resourceBlock the resource block
492             * @throws SystemException if a system exception occurred
493             */
494            @Override
495            @Transactional(
496                    isolation = Isolation.READ_COMMITTED,
497                    propagation = Propagation.REQUIRES_NEW)
498            public void releaseResourceBlock(ResourceBlock resourceBlock)
499                    throws SystemException {
500    
501                    releaseResourceBlock(resourceBlock.getResourceBlockId());
502            }
503    
504            @Override
505            public void removeAllGroupScopePermissions(
506                            long companyId, String name, long roleId, long actionIdsLong)
507                    throws SystemException {
508    
509                    List<ResourceTypePermission> resourceTypePermissions =
510                            resourceTypePermissionLocalService.
511                                    getGroupScopeResourceTypePermissions(companyId, name, roleId);
512    
513                    for (ResourceTypePermission resourceTypePermission :
514                                    resourceTypePermissions) {
515    
516                            removeGroupScopePermissions(
517                                    companyId, resourceTypePermission.getGroupId(), name, roleId,
518                                    actionIdsLong);
519                    }
520            }
521    
522            @Override
523            public void removeAllGroupScopePermissions(
524                            long companyId, String name, long roleId, String actionId)
525                    throws PortalException, SystemException {
526    
527                    removeAllGroupScopePermissions(
528                            companyId, name, roleId, getActionId(name, actionId));
529            }
530    
531            @Override
532            public void removeCompanyScopePermission(
533                            long companyId, String name, long roleId, String actionId)
534                    throws PortalException, SystemException {
535    
536                    updateCompanyScopePermissions(
537                            companyId, name, roleId, getActionId(name, actionId),
538                            ResourceBlockConstants.OPERATOR_REMOVE);
539            }
540    
541            @Override
542            public void removeCompanyScopePermissions(
543                            long companyId, String name, long roleId, long actionIdsLong)
544                    throws SystemException {
545    
546                    updateCompanyScopePermissions(
547                            companyId, name, roleId, actionIdsLong,
548                            ResourceBlockConstants.OPERATOR_REMOVE);
549            }
550    
551            @Override
552            public void removeGroupScopePermission(
553                            long companyId, long groupId, String name, long roleId,
554                            String actionId)
555                    throws PortalException, SystemException {
556    
557                    updateGroupScopePermissions(
558                            companyId, groupId, name, roleId, getActionId(name, actionId),
559                            ResourceBlockConstants.OPERATOR_REMOVE);
560            }
561    
562            @Override
563            public void removeGroupScopePermissions(
564                            long companyId, long groupId, String name, long roleId,
565                            long actionIdsLong)
566                    throws SystemException {
567    
568                    updateGroupScopePermissions(
569                            companyId, groupId, name, roleId, actionIdsLong,
570                            ResourceBlockConstants.OPERATOR_REMOVE);
571            }
572    
573            @Override
574            public void removeIndividualScopePermission(
575                            long companyId, long groupId, String name, long primKey,
576                            long roleId, String actionId)
577                    throws PortalException, SystemException {
578    
579                    PermissionedModel permissionedModel = getPermissionedModel(
580                            name, primKey);
581    
582                    updateIndividualScopePermissions(
583                            companyId, groupId, name, permissionedModel, roleId,
584                            getActionId(name, actionId),
585                            ResourceBlockConstants.OPERATOR_REMOVE);
586            }
587    
588            @Override
589            public void removeIndividualScopePermission(
590                            long companyId, long groupId, String name,
591                            PermissionedModel permissionedModel, long roleId, String actionId)
592                    throws PortalException, SystemException {
593    
594                    updateIndividualScopePermissions(
595                            companyId, groupId, name, permissionedModel, roleId,
596                            getActionId(name, actionId),
597                            ResourceBlockConstants.OPERATOR_REMOVE);
598            }
599    
600            @Override
601            public void removeIndividualScopePermissions(
602                            long companyId, long groupId, String name, long primKey,
603                            long roleId, long actionIdsLong)
604                    throws PortalException, SystemException {
605    
606                    PermissionedModel permissionedModel = getPermissionedModel(
607                            name, primKey);
608    
609                    updateIndividualScopePermissions(
610                            companyId, groupId, name, permissionedModel, roleId, actionIdsLong,
611                            ResourceBlockConstants.OPERATOR_REMOVE);
612            }
613    
614            @Override
615            public void removeIndividualScopePermissions(
616                            long companyId, long groupId, String name,
617                            PermissionedModel permissionedModel, long roleId,
618                            long actionIdsLong)
619                    throws SystemException {
620    
621                    updateIndividualScopePermissions(
622                            companyId, groupId, name, permissionedModel, roleId, actionIdsLong,
623                            ResourceBlockConstants.OPERATOR_REMOVE);
624            }
625    
626            @Override
627            public void setCompanyScopePermissions(
628                            long companyId, String name, long roleId, List<String> actionIds)
629                    throws PortalException, SystemException {
630    
631                    checkGuestSupportedPermission(companyId, name, roleId, actionIds);
632    
633                    updateCompanyScopePermissions(
634                            companyId, name, roleId, getActionIds(name, actionIds),
635                            ResourceBlockConstants.OPERATOR_SET);
636            }
637    
638            @Override
639            public void setCompanyScopePermissions(
640                            long companyId, String name, long roleId, long actionIdsLong)
641                    throws SystemException {
642    
643                    updateCompanyScopePermissions(
644                            companyId, name, roleId, actionIdsLong,
645                            ResourceBlockConstants.OPERATOR_SET);
646            }
647    
648            @Override
649            public void setGroupScopePermissions(
650                            long companyId, long groupId, String name, long roleId,
651                            List<String> actionIds)
652                    throws PortalException, SystemException {
653    
654                    checkGuestSupportedPermission(companyId, name, roleId, actionIds);
655    
656                    updateGroupScopePermissions(
657                            companyId, groupId, name, roleId, getActionIds(name, actionIds),
658                            ResourceBlockConstants.OPERATOR_SET);
659            }
660    
661            @Override
662            public void setGroupScopePermissions(
663                            long companyId, long groupId, String name, long roleId,
664                            long actionIdsLong)
665                    throws SystemException {
666    
667                    updateGroupScopePermissions(
668                            companyId, groupId, name, roleId, actionIdsLong,
669                            ResourceBlockConstants.OPERATOR_SET);
670            }
671    
672            @Override
673            public void setIndividualScopePermissions(
674                            long companyId, long groupId, String name, long primKey,
675                            long roleId, List<String> actionIds)
676                    throws PortalException, SystemException {
677    
678                    PermissionedModel permissionedModel = getPermissionedModel(
679                            name, primKey);
680    
681                    checkGuestSupportedPermission(companyId, name, roleId, actionIds);
682    
683                    updateIndividualScopePermissions(
684                            companyId, groupId, name, permissionedModel, roleId,
685                            getActionIds(name, actionIds), ResourceBlockConstants.OPERATOR_SET);
686            }
687    
688            @Override
689            public void setIndividualScopePermissions(
690                            long companyId, long groupId, String name, long primKey,
691                            long roleId, long actionIdsLong)
692                    throws PortalException, SystemException {
693    
694                    PermissionedModel permissionedModel = getPermissionedModel(
695                            name, primKey);
696    
697                    updateIndividualScopePermissions(
698                            companyId, groupId, name, permissionedModel, roleId, actionIdsLong,
699                            ResourceBlockConstants.OPERATOR_SET);
700            }
701    
702            @Override
703            public void setIndividualScopePermissions(
704                            long companyId, long groupId, String name, long primKey,
705                            Map<Long, String[]> roleIdsToActionIds)
706                    throws PortalException, SystemException {
707    
708                    boolean flushResourceBlockEnabled =
709                            PermissionThreadLocal.isFlushResourceBlockEnabled(
710                                    companyId, groupId, name);
711    
712                    PermissionThreadLocal.setFlushResourceBlockEnabled(
713                            companyId, groupId, name, false);
714    
715                    try {
716                            PermissionedModel permissionedModel = getPermissionedModel(
717                                    name, primKey);
718    
719                            for (Map.Entry<Long, String[]> entry :
720                                            roleIdsToActionIds.entrySet()) {
721    
722                                    long roleId = entry.getKey();
723                                    List<String> actionIds = ListUtil.fromArray(entry.getValue());
724    
725                                    checkGuestSupportedPermission(
726                                            companyId, name, roleId, actionIds);
727    
728                                    updateIndividualScopePermissions(
729                                            companyId, groupId, name, permissionedModel, roleId,
730                                            getActionIds(name, actionIds),
731                                            ResourceBlockConstants.OPERATOR_SET);
732                            }
733                    }
734                    finally {
735                            PermissionThreadLocal.setFlushResourceBlockEnabled(
736                                    companyId, groupId, name, flushResourceBlockEnabled);
737    
738                            PermissionCacheUtil.clearResourceBlockCache(
739                                    companyId, groupId, name);
740                    }
741            }
742    
743            @Override
744            public void setIndividualScopePermissions(
745                            long companyId, long groupId, String name,
746                            PermissionedModel permissionedModel, long roleId,
747                            List<String> actionIds)
748                    throws PortalException, SystemException {
749    
750                    checkGuestSupportedPermission(companyId, name, roleId, actionIds);
751    
752                    updateIndividualScopePermissions(
753                            companyId, groupId, name, permissionedModel, roleId,
754                            getActionIds(name, actionIds), ResourceBlockConstants.OPERATOR_SET);
755            }
756    
757            @Override
758            public void setIndividualScopePermissions(
759                            long companyId, long groupId, String name,
760                            PermissionedModel permissionedModel, long roleId,
761                            long actionIdsLong)
762                    throws SystemException {
763    
764                    updateIndividualScopePermissions(
765                            companyId, groupId, name, permissionedModel, roleId, actionIdsLong,
766                            ResourceBlockConstants.OPERATOR_SET);
767            }
768    
769            @Override
770            public void updateCompanyScopePermissions(
771                            long companyId, String name, long roleId, long actionIdsLong,
772                            int operator)
773                    throws SystemException {
774    
775                    resourceTypePermissionLocalService.
776                            updateCompanyScopeResourceTypePermissions(
777                                    companyId, name, roleId, actionIdsLong, operator);
778    
779                    List<ResourceBlock> resourceBlocks = resourceBlockPersistence.findByC_N(
780                            companyId, name);
781    
782                    updatePermissions(resourceBlocks, roleId, actionIdsLong, operator);
783    
784                    PermissionCacheUtil.clearResourceCache();
785            }
786    
787            @Override
788            public void updateGroupScopePermissions(
789                            long companyId, long groupId, String name, long roleId,
790                            long actionIdsLong, int operator)
791                    throws SystemException {
792    
793                    resourceTypePermissionLocalService.
794                            updateGroupScopeResourceTypePermissions(
795                                    companyId, groupId, name, roleId, actionIdsLong, operator);
796    
797                    List<ResourceBlock> resourceBlocks =
798                            resourceBlockPersistence.findByC_G_N(companyId, groupId, name);
799    
800                    updatePermissions(resourceBlocks, roleId, actionIdsLong, operator);
801    
802                    PermissionCacheUtil.clearResourceCache();
803            }
804    
805            @Override
806            public void updateIndividualScopePermissions(
807                            long companyId, long groupId, String name,
808                            PermissionedModel permissionedModel, long roleId,
809                            long actionIdsLong, int operator)
810                    throws SystemException {
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            public ResourceBlock updateResourceBlockId(
867                            long companyId, long groupId, String name,
868                            final PermissionedModel permissionedModel, String permissionsHash,
869                            ResourceBlockPermissionsContainer resourceBlockPermissionsContainer)
870                    throws SystemException {
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 = DBFactoryUtil.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.createSQLQuery(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                    TransactionCommitCallbackRegistryUtil.registerCallback(callable);
989    
990                    return resourceBlock;
991            }
992    
993            @Override
994            public void verifyResourceBlockId(long companyId, String name, long primKey)
995                    throws PortalException, SystemException {
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, SystemException {
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, SystemException {
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                    throws SystemException {
1069    
1070                    for (ResourceBlock resourceBlock : resourceBlocks) {
1071                            resourceBlockPermissionLocalService.updateResourceBlockPermission(
1072                                    resourceBlock.getPrimaryKey(), roleId, actionIdsLong, operator);
1073    
1074                            updatePermissionsHash(resourceBlock);
1075                    }
1076            }
1077    
1078            protected void updatePermissionsHash(ResourceBlock resourceBlock)
1079                    throws SystemException {
1080    
1081                    ResourceBlockPermissionsContainer resourceBlockPermissionsContainer =
1082                            resourceBlockPermissionLocalService.
1083                            getResourceBlockPermissionsContainer(resourceBlock.getPrimaryKey());
1084    
1085                    String permissionsHash =
1086                            resourceBlockPermissionsContainer.getPermissionsHash();
1087    
1088                    resourceBlock.setPermissionsHash(permissionsHash);
1089    
1090                    updateResourceBlock(resourceBlock);
1091            }
1092    
1093            private static final String _DELETE_RESOURCE_BLOCK =
1094                    ResourceBlockLocalServiceImpl.class.getName() +
1095                            ".deleteResourceBlock";
1096    
1097            private static final String _RELEASE_RESOURCE_BLOCK =
1098                    ResourceBlockLocalServiceImpl.class.getName() +
1099                            ".releaseResourceBlock";
1100    
1101            private static final String _RETAIN_RESOURCE_BLOCK =
1102                    ResourceBlockLocalServiceImpl.class.getName() +
1103                            ".retainResourceBlock";
1104    
1105            private static Log _log = LogFactoryUtil.getLog(
1106                    ResourceBlockLocalServiceImpl.class);
1107    
1108    }