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