001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.portal.ResourceBlocksNotSupportedException;
018    import com.liferay.portal.kernel.dao.db.DB;
019    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
020    import com.liferay.portal.kernel.dao.jdbc.CurrentConnectionUtil;
021    import com.liferay.portal.kernel.dao.orm.ORMException;
022    import com.liferay.portal.kernel.dao.orm.QueryPos;
023    import com.liferay.portal.kernel.dao.orm.SQLQuery;
024    import com.liferay.portal.kernel.dao.orm.Session;
025    import com.liferay.portal.kernel.exception.PortalException;
026    import com.liferay.portal.kernel.exception.SystemException;
027    import com.liferay.portal.kernel.log.Log;
028    import com.liferay.portal.kernel.log.LogFactoryUtil;
029    import com.liferay.portal.kernel.transaction.Isolation;
030    import com.liferay.portal.kernel.transaction.Propagation;
031    import com.liferay.portal.kernel.transaction.TransactionCommitCallbackRegistryUtil;
032    import com.liferay.portal.kernel.transaction.Transactional;
033    import com.liferay.portal.kernel.util.ListUtil;
034    import com.liferay.portal.model.AuditedModel;
035    import com.liferay.portal.model.GroupedModel;
036    import com.liferay.portal.model.PermissionedModel;
037    import com.liferay.portal.model.PersistedModel;
038    import com.liferay.portal.model.ResourceAction;
039    import com.liferay.portal.model.ResourceBlock;
040    import com.liferay.portal.model.ResourceBlockConstants;
041    import com.liferay.portal.model.ResourceBlockPermissionsContainer;
042    import com.liferay.portal.model.ResourceTypePermission;
043    import com.liferay.portal.model.Role;
044    import com.liferay.portal.model.RoleConstants;
045    import com.liferay.portal.model.impl.ResourceBlockImpl;
046    import com.liferay.portal.security.auth.PrincipalException;
047    import com.liferay.portal.security.permission.PermissionCacheUtil;
048    import com.liferay.portal.security.permission.PermissionThreadLocal;
049    import com.liferay.portal.security.permission.ResourceActionsUtil;
050    import com.liferay.portal.security.permission.ResourceBlockIdsBag;
051    import com.liferay.portal.service.PersistedModelLocalService;
052    import com.liferay.portal.service.PersistedModelLocalServiceRegistryUtil;
053    import com.liferay.portal.service.base.ResourceBlockLocalServiceBaseImpl;
054    import com.liferay.portal.util.PropsValues;
055    import com.liferay.util.dao.orm.CustomSQLUtil;
056    
057    import java.sql.Connection;
058    import java.sql.SQLException;
059    
060    import java.util.ArrayList;
061    import java.util.List;
062    import java.util.Map;
063    import java.util.concurrent.Callable;
064    
065    import javax.sql.DataSource;
066    
067    /**
068     * Provides the local service for accessing, adding, deleting, and updating
069     * resource blocks.
070     *
071     * @author Connor McKay
072     * @author Shuyang Zhou
073     */
074    public class ResourceBlockLocalServiceImpl
075            extends ResourceBlockLocalServiceBaseImpl {
076    
077            @Override
078            public void addCompanyScopePermission(
079                            long companyId, String name, long roleId, String actionId)
080                    throws PortalException, 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                    PermissionCacheUtil.clearResourceCache();
780            }
781    
782            @Override
783            public void updateGroupScopePermissions(
784                            long companyId, long groupId, String name, long roleId,
785                            long actionIdsLong, int operator)
786                    throws SystemException {
787    
788                    resourceTypePermissionLocalService.
789                            updateGroupScopeResourceTypePermissions(
790                                    companyId, groupId, name, roleId, actionIdsLong, operator);
791    
792                    PermissionCacheUtil.clearResourceCache();
793            }
794    
795            @Override
796            public void updateIndividualScopePermissions(
797                            long companyId, long groupId, String name,
798                            PermissionedModel permissionedModel, long roleId,
799                            long actionIdsLong, int operator)
800                    throws SystemException {
801    
802                    ResourceBlock resourceBlock =
803                            resourceBlockPersistence.fetchByPrimaryKey(
804                                    permissionedModel.getResourceBlockId());
805    
806                    ResourceBlockPermissionsContainer resourceBlockPermissionsContainer =
807                            null;
808    
809                    if (resourceBlock == null) {
810                            resourceBlockPermissionsContainer =
811                                    resourceTypePermissionLocalService.
812                                            getResourceBlockPermissionsContainer(
813                                                    companyId, groupId, name);
814                    }
815                    else {
816                            resourceBlockPermissionsContainer =
817                                    resourceBlockPermissionLocalService.
818                                            getResourceBlockPermissionsContainer(
819                                                    resourceBlock.getPrimaryKey());
820                    }
821    
822                    long oldActionIdsLong = resourceBlockPermissionsContainer.getActionIds(
823                            roleId);
824    
825                    if (operator == ResourceBlockConstants.OPERATOR_ADD) {
826                            actionIdsLong |= oldActionIdsLong;
827                    }
828                    else if (operator == ResourceBlockConstants.OPERATOR_REMOVE) {
829                            actionIdsLong = oldActionIdsLong & (~actionIdsLong);
830                    }
831    
832                    if (resourceBlock != null) {
833                            if (oldActionIdsLong == actionIdsLong) {
834                                    return;
835                            }
836    
837                            resourceBlockLocalService.releaseResourceBlock(resourceBlock);
838                    }
839    
840                    resourceBlockPermissionsContainer.setPermissions(roleId, actionIdsLong);
841    
842                    String permissionsHash =
843                            resourceBlockPermissionsContainer.getPermissionsHash();
844    
845                    resourceBlockLocalService.updateResourceBlockId(
846                            companyId, groupId, name, permissionedModel, permissionsHash,
847                            resourceBlockPermissionsContainer);
848    
849                    PermissionCacheUtil.clearResourceBlockCache(companyId, groupId, name);
850            }
851    
852            @Override
853            @Transactional(
854                    isolation = Isolation.READ_COMMITTED,
855                    propagation = Propagation.REQUIRES_NEW)
856            public ResourceBlock updateResourceBlockId(
857                            long companyId, long groupId, String name,
858                            final PermissionedModel permissionedModel, String permissionsHash,
859                            ResourceBlockPermissionsContainer resourceBlockPermissionsContainer)
860                    throws SystemException {
861    
862                    ResourceBlock resourceBlock = null;
863    
864                    while (true) {
865                            resourceBlock = resourceBlockPersistence.fetchByC_G_N_P(
866                                    companyId, groupId, name, permissionsHash, false);
867    
868                            if (resourceBlock == null) {
869                                    try {
870                                            resourceBlock = addResourceBlock(
871                                                    companyId, groupId, name, permissionsHash,
872                                                    resourceBlockPermissionsContainer);
873    
874                                            // On success, manually flush to enforce database row lock
875    
876                                            if (PropsValues.SPRING_HIBERNATE_SESSION_DELEGATED) {
877                                                    resourceBlockPersistence.flush();
878                                            }
879                                    }
880                                    catch (SystemException se) {
881                                            if (_log.isWarnEnabled()) {
882                                                    _log.warn(
883                                                            "Unable to add a new resource block. Retrying");
884                                            }
885    
886                                            // On failure, cancel all pending persistent entities
887    
888                                            Session session =
889                                                    resourceBlockPersistence.getCurrentSession();
890    
891                                            session.clear();
892    
893                                            DB db = DBFactoryUtil.getDB();
894    
895                                            if (!db.isSupportsQueryingAfterException()) {
896                                                    DataSource dataSource =
897                                                            resourceBlockPersistence.getDataSource();
898    
899                                                    Connection connection =
900                                                            CurrentConnectionUtil.getConnection(dataSource);
901    
902                                                    try {
903                                                            connection.rollback();
904    
905                                                            connection.setAutoCommit(false);
906                                                    }
907                                                    catch (SQLException sqle) {
908                                                            throw new SystemException(sqle);
909                                                    }
910                                            }
911    
912                                            continue;
913                                    }
914    
915                                    break;
916                            }
917    
918                            Session session = resourceBlockPersistence.openSession();
919    
920                            try {
921                                    String sql = CustomSQLUtil.get(_RETAIN_RESOURCE_BLOCK);
922    
923                                    SQLQuery sqlQuery = session.createSQLQuery(sql);
924    
925                                    QueryPos qPos = QueryPos.getInstance(sqlQuery);
926    
927                                    qPos.add(resourceBlock.getResourceBlockId());
928    
929                                    if (sqlQuery.executeUpdate() > 0) {
930    
931                                            // We currently use an "update set" SQL statement to
932                                            // increment the reference count in a discontinuous manner.
933                                            // We can change it to an "update where" SQL statement to
934                                            // guarantee continuous counts. We are using a SQL statement
935                                            // that allows for a discontinuous count since it is cheaper
936                                            // and continuity is not required.
937    
938                                            resourceBlock.setReferenceCount(
939                                                    resourceBlock.getReferenceCount() + 1);
940    
941                                            break;
942                                    }
943                            }
944                            catch (ORMException orme) {
945                                    if (_log.isWarnEnabled()) {
946                                            _log.warn(
947                                                    "Unable to increment reference count for resource " +
948                                                            "block " + resourceBlock.getResourceBlockId() +
949                                                                    ". Retrying");
950                                    }
951                            }
952                            finally {
953    
954                                    // Prevent Hibernate from automatically flushing out the first
955                                    // level cache since that will lead to a regular update that
956                                    // will overwrite the previous update causing a lost update.
957    
958                                    session.evict(resourceBlock);
959    
960                                    resourceBlockPersistence.closeSession(session);
961                            }
962                    }
963    
964                    permissionedModel.setResourceBlockId(
965                            resourceBlock.getResourceBlockId());
966    
967                    Callable<Void> callable = new Callable<Void>() {
968    
969                            @Override
970                            public Void call() throws Exception {
971                                    permissionedModel.persist();
972    
973                                    return null;
974                            }
975    
976                    };
977    
978                    TransactionCommitCallbackRegistryUtil.registerCallback(callable);
979    
980                    return resourceBlock;
981            }
982    
983            @Override
984            public void verifyResourceBlockId(long companyId, String name, long primKey)
985                    throws PortalException, SystemException {
986    
987                    PermissionedModel permissionedModel = getPermissionedModel(
988                            name, primKey);
989    
990                    ResourceBlock resourceBlock =
991                            resourceBlockPersistence.fetchByPrimaryKey(
992                                    permissionedModel.getResourceBlockId());
993    
994                    if (resourceBlock != null) {
995                            return;
996                    }
997    
998                    if (_log.isWarnEnabled()) {
999                            _log.warn(
1000                                    "Resource block " + permissionedModel.getResourceBlockId() +
1001                                            " missing for " + name + "#" + primKey);
1002                    }
1003    
1004                    long groupId = 0;
1005                    long ownerId = 0;
1006    
1007                    if (permissionedModel instanceof GroupedModel) {
1008                            GroupedModel groupedModel = (GroupedModel)permissionedModel;
1009    
1010                            groupId = groupedModel.getGroupId();
1011                            ownerId = groupedModel.getUserId();
1012                    }
1013                    else if (permissionedModel instanceof AuditedModel) {
1014                            AuditedModel auditedModel = (AuditedModel)permissionedModel;
1015    
1016                            ownerId = auditedModel.getUserId();
1017                    }
1018    
1019                    resourceLocalService.addResources(
1020                            companyId, groupId, ownerId, name, primKey, false, true, true);
1021            }
1022    
1023            protected void checkGuestSupportedPermission(
1024                            long companyId, String name, long roleId, List<String> actionIds)
1025                    throws PortalException, SystemException {
1026    
1027                    if (!isGuestRole(companyId, roleId)) {
1028                            return;
1029                    }
1030    
1031                    List<String> unsupportedActionIds =
1032                            ResourceActionsUtil.getResourceGuestUnsupportedActions(name, name);
1033    
1034                    for (String actionId : actionIds) {
1035                            if (unsupportedActionIds.contains(actionId)) {
1036                                    throw new PrincipalException(
1037                                            actionId + "is not supported by role " + roleId);
1038                            }
1039                    }
1040            }
1041    
1042            protected boolean isGuestRole(long companyId, long roleId)
1043                    throws PortalException, SystemException {
1044    
1045                    Role guestRole = roleLocalService.getRole(
1046                            companyId, RoleConstants.GUEST);
1047    
1048                    if (roleId == guestRole.getRoleId()) {
1049                            return true;
1050                    }
1051    
1052                    return false;
1053            }
1054    
1055            protected void updatePermissions(
1056                            List<ResourceBlock> resourceBlocks, long roleId, long actionIdsLong,
1057                            int operator)
1058                    throws SystemException {
1059    
1060                    for (ResourceBlock resourceBlock : resourceBlocks) {
1061                            resourceBlockPermissionLocalService.updateResourceBlockPermission(
1062                                    resourceBlock.getPrimaryKey(), roleId, actionIdsLong, operator);
1063    
1064                            updatePermissionsHash(resourceBlock);
1065                    }
1066            }
1067    
1068            protected void updatePermissionsHash(ResourceBlock resourceBlock)
1069                    throws SystemException {
1070    
1071                    ResourceBlockPermissionsContainer resourceBlockPermissionsContainer =
1072                            resourceBlockPermissionLocalService.
1073                            getResourceBlockPermissionsContainer(resourceBlock.getPrimaryKey());
1074    
1075                    String permissionsHash =
1076                            resourceBlockPermissionsContainer.getPermissionsHash();
1077    
1078                    resourceBlock.setPermissionsHash(permissionsHash);
1079    
1080                    updateResourceBlock(resourceBlock);
1081            }
1082    
1083            private static final String _DELETE_RESOURCE_BLOCK =
1084                    ResourceBlockLocalServiceImpl.class.getName() +
1085                            ".deleteResourceBlock";
1086    
1087            private static final String _RELEASE_RESOURCE_BLOCK =
1088                    ResourceBlockLocalServiceImpl.class.getName() +
1089                            ".releaseResourceBlock";
1090    
1091            private static final String _RETAIN_RESOURCE_BLOCK =
1092                    ResourceBlockLocalServiceImpl.class.getName() +
1093                            ".retainResourceBlock";
1094    
1095            private static Log _log = LogFactoryUtil.getLog(
1096                    ResourceBlockLocalServiceImpl.class);
1097    
1098    }