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