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