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.ResourceActionsException;
018    import com.liferay.portal.kernel.bean.BeanPropertiesUtil;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.search.SearchEngineUtil;
024    import com.liferay.portal.kernel.util.ListUtil;
025    import com.liferay.portal.model.AuditedModel;
026    import com.liferay.portal.model.GroupedModel;
027    import com.liferay.portal.model.PermissionedModel;
028    import com.liferay.portal.model.Resource;
029    import com.liferay.portal.model.ResourceConstants;
030    import com.liferay.portal.model.ResourcePermission;
031    import com.liferay.portal.model.Role;
032    import com.liferay.portal.model.RoleConstants;
033    import com.liferay.portal.model.impl.ResourceImpl;
034    import com.liferay.portal.security.permission.PermissionCacheUtil;
035    import com.liferay.portal.security.permission.PermissionThreadLocal;
036    import com.liferay.portal.security.permission.ResourceActionsUtil;
037    import com.liferay.portal.service.ServiceContext;
038    import com.liferay.portal.service.base.ResourceLocalServiceBaseImpl;
039    import com.liferay.portal.util.ResourcePermissionsThreadLocal;
040    
041    import java.util.Arrays;
042    import java.util.Iterator;
043    import java.util.List;
044    
045    import org.apache.commons.lang.time.StopWatch;
046    
047    /**
048     * Provides the local service for accessing, adding, and updating resources.
049     *
050     * <p>
051     * Permissions in Liferay are defined for resource/action pairs. Some resources,
052     * known as portlet resources, define actions that the end-user can perform with
053     * respect to a portlet window. Other resources, known as model resources,
054     * define actions that the end-user can perform with respect to the
055     * service/persistence layer.
056     * </p>
057     *
058     * <p>
059     * On creating an entity instance, you should create resources for it. The
060     * following example demonstrates adding resources for an instance of a model
061     * entity named <code>SomeWidget</code>. The IDs of the actions permitted for
062     * the group and guests are passed in from the service context.
063     * </p>
064     *
065     * <pre>
066     * <code>
067     * resourceLocalService.addModelResources(
068     *              SomeWidget.getCompanyId(), SomeWidget.getGroupId(), userId,
069     *              SomeWidget.class.getName(), SomeWidget.getPrimaryKey(),
070     *              serviceContext.getGroupPermissions, serviceContext.getGuestPermissions);
071     * </code>
072     * </pre>
073     *
074     * <p>
075     * Just prior to deleting an entity instance, you should delete its resource at
076     * the individual scope. The following example demonstrates deleting a resource
077     * associated with the <code>SomeWidget</code> model entity at the scope
078     * individual scope.
079     * </p>
080     *
081     * <pre>
082     * <code>
083     * resourceLocalService.deleteResource(
084     *              SomeWidget.getCompanyId(), SomeWidget.class.getName(),
085     *              ResourceConstants.SCOPE_INDIVIDUAL, SomeWidget.getPrimaryKey());
086     * </code>
087     * </pre>
088     *
089     * @author Brian Wing Shun Chan
090     * @author Wilson S. Man
091     * @author Raymond Augé
092     * @author Julio Camarero
093     * @author Connor McKay
094     */
095    public class ResourceLocalServiceImpl extends ResourceLocalServiceBaseImpl {
096    
097            /**
098             * Adds resources for the model, always creating a resource at the
099             * individual scope and only creating resources at the group, group
100             * template, and company scope if such resources don't already exist.
101             *
102             * <ol>
103             * <li>
104             * If the service context specifies that default group or default guest
105             * permissions are to be added, then only default permissions are added. See
106             * {@link com.liferay.portal.service.ServiceContext#setAddGroupPermissions(
107             * boolean)} and {@link
108             * com.liferay.portal.service.ServiceContext#setAddGuestPermissions(
109             * boolean)}.
110             * </li>
111             * <li>
112             * Else ...
113             * <ol>
114             * <li>
115             * If the service context specifies to derive default permissions, then
116             * default group and guest permissions are derived from the model and
117             * added. See {@link
118             * com.liferay.portal.service.ServiceContext#setDeriveDefaultPermissions(
119             * boolean)}.
120             * </li>
121             * <li>
122             * Lastly group and guest permissions from the service
123             * context are applied. See {@link
124             * com.liferay.portal.service.ServiceContext#setGroupPermissions(String[])}
125             * and {@link
126             * com.liferay.portal.service.ServiceContext#setGuesPermissions(String[])}.
127             * </li>
128             * </ol>
129             *
130             * </li>
131             * </ol>
132             *
133             * @param  auditedModel the model to associate with the resources
134             * @param  serviceContext the service context to apply. Can set whether to
135             *         add the model's default group and guest permissions, set whether
136             *         to derive default group and guest permissions from the model, set
137             *         group permissions to apply, and set guest permissions to apply.
138             * @throws PortalException if no portal actions could be found associated
139             *         with the model or if a portal exception occurred
140             * @throws SystemException if a system exception occurred
141             */
142            public void addModelResources(
143                            AuditedModel auditedModel, ServiceContext serviceContext)
144                    throws PortalException, SystemException {
145    
146                    if (serviceContext.isAddGroupPermissions() ||
147                            serviceContext.isAddGuestPermissions()) {
148    
149                            addResources(
150                                    auditedModel.getCompanyId(), getGroupId(auditedModel),
151                                    auditedModel.getUserId(), auditedModel.getModelClassName(),
152                                    String.valueOf(auditedModel.getPrimaryKeyObj()), false,
153                                    serviceContext.isAddGroupPermissions(),
154                                    serviceContext.isAddGuestPermissions(),
155                                    getPermissionedModel(auditedModel));
156                    }
157                    else {
158                            if (serviceContext.isDeriveDefaultPermissions()) {
159                                    serviceContext.deriveDefaultPermissions(
160                                            getGroupId(auditedModel), auditedModel.getModelClassName());
161                            }
162    
163                            addModelResources(
164                                    auditedModel.getCompanyId(), getGroupId(auditedModel),
165                                    auditedModel.getUserId(), auditedModel.getModelClassName(),
166                                    String.valueOf(auditedModel.getPrimaryKeyObj()),
167                                    serviceContext.getGroupPermissions(),
168                                    serviceContext.getGuestPermissions(),
169                                    getPermissionedModel(auditedModel));
170                    }
171            }
172    
173            /**
174             * Adds resources for the model with the name and primary key, always
175             * creating a resource at the individual scope and only creating resources
176             * at the group, group template, and company scope if such resources don't
177             * already exist.
178             *
179             * @param  companyId the primary key of the portal instance
180             * @param  groupId the primary key of the group
181             * @param  userId the primary key of the user adding the resources
182             * @param  name a name for the resource, typically the model's class name
183             * @param  primKey the primary key of the model instance, optionally
184             *         <code>0</code> if no instance exists
185             * @param  groupPermissions the group permissions to be applied
186             * @param  guestPermissions the guest permissions to be applied
187             * @throws PortalException if no portal actions could be found associated
188             *         with the model or if a portal exception occurred
189             * @throws SystemException if a system exception occurred
190             */
191            public void addModelResources(
192                            long companyId, long groupId, long userId, String name,
193                            long primKey, String[] groupPermissions, String[] guestPermissions)
194                    throws PortalException, SystemException {
195    
196                    addModelResources(
197                            companyId, groupId, userId, name, String.valueOf(primKey),
198                            groupPermissions, guestPermissions, null);
199            }
200    
201            /**
202             * Adds resources for the model with the name and primary key string, always
203             * creating a resource at the individual scope and only creating resources
204             * at the group, group template, and company scope if such resources don't
205             * already exist.
206             *
207             * @param  companyId the primary key of the portal instance
208             * @param  groupId the primary key of the group
209             * @param  userId the primary key of the user adding the resources
210             * @param  name a name for the resource, typically the model's class name
211             * @param  primKey the primary key string of the model instance, optionally
212             *         an empty string if no instance exists
213             * @param  groupPermissions the group permissions to be applied
214             * @param  guestPermissions the guest permissions to be applied
215             * @throws PortalException if no portal actions could be found associated
216             *         with the model or if a portal exception occurred
217             * @throws SystemException if a system exception occurred
218             */
219            public void addModelResources(
220                            long companyId, long groupId, long userId, String name,
221                            String primKey, String[] groupPermissions,
222                            String[] guestPermissions)
223                    throws PortalException, SystemException {
224    
225                    addModelResources(
226                            companyId, groupId, userId, name, primKey, groupPermissions,
227                            guestPermissions, null);
228            }
229    
230            /**
231             * Adds resources for the entity with the name and primary key, always
232             * creating a resource at the individual scope and only creating resources
233             * at the group, group template, and company scope if such resources don't
234             * already exist.
235             *
236             * @param  companyId the primary key of the portal instance
237             * @param  groupId the primary key of the group
238             * @param  userId the primary key of the user adding the resources
239             * @param  name a name for the resource, which should be a portlet ID if the
240             *         resource is a portlet or the resource's class name otherwise
241             * @param  primKey the primary key of the resource instance, optionally
242             *         <code>0</code> if no instance exists
243             * @param  portletActions whether to associate portlet actions with the
244             *         resource
245             * @param  addGroupPermissions whether to add group permissions
246             * @param  addGuestPermissions whether to add guest permissions
247             * @throws PortalException if no portal actions could be found associated
248             *         with the resource or if a portal exception occurred
249             * @throws SystemException if a system exception occurred
250             */
251            public void addResources(
252                            long companyId, long groupId, long userId, String name,
253                            long primKey, boolean portletActions, boolean addGroupPermissions,
254                            boolean addGuestPermissions)
255                    throws PortalException, SystemException {
256    
257                    addResources(
258                            companyId, groupId, userId, name, String.valueOf(primKey),
259                            portletActions, addGroupPermissions, addGuestPermissions, null);
260            }
261    
262            /**
263             * Adds resources for the entity with the name and primary key string,
264             * always creating a resource at the individual scope and only creating
265             * resources at the group, group template, and company scope if such
266             * resources don't already exist.
267             *
268             * @param  companyId the primary key of the portal instance
269             * @param  groupId the primary key of the group
270             * @param  userId the primary key of the user adding the resources
271             * @param  name a name for the resource, which should be a portlet ID if the
272             *         resource is a portlet or the resource's class name otherwise
273             * @param  primKey the primary key string of the resource instance,
274             *         optionally an empty string if no instance exists
275             * @param  portletActions whether to associate portlet actions with the
276             *         resource
277             * @param  addGroupPermissions whether to add group permissions
278             * @param  addGuestPermissions whether to add guest permissions
279             * @throws PortalException if no portal actions could be found associated
280             *         with the resource or if a portal exception occurred
281             * @throws SystemException if a system exception occurred
282             */
283            public void addResources(
284                            long companyId, long groupId, long userId, String name,
285                            String primKey, boolean portletActions, boolean addGroupPermissions,
286                            boolean addGuestPermissions)
287                    throws PortalException, SystemException {
288    
289                    addResources(
290                            companyId, groupId, userId, name, primKey, portletActions,
291                            addGroupPermissions, addGuestPermissions, null);
292            }
293    
294            /**
295             * Adds resources for the entity with the name. Use this method if the user
296             * is unknown or irrelevant and there is no current entity instance.
297             *
298             * @param  companyId the primary key of the portal instance
299             * @param  groupId the primary key of the group
300             * @param  name a name for the resource, which should be a portlet ID if the
301             *         resource is a portlet or the resource's class name otherwise
302             * @param  portletActions whether to associate portlet actions with the
303             *         resource
304             * @throws PortalException if no portal actions could be found associated
305             *         with the resource or if a portal exception occurred
306             * @throws SystemException if a system exception occurred
307             */
308            public void addResources(
309                            long companyId, long groupId, String name, boolean portletActions)
310                    throws PortalException, SystemException {
311    
312                    addResources(
313                            companyId, groupId, 0, name, null, portletActions, false, false);
314            }
315    
316            /**
317             * Deletes the resource associated with the model at the scope.
318             *
319             * @param  auditedModel the model associated with the resource
320             * @param  scope the scope of the resource. For more information see {@link
321             *         com.liferay.portal.model.ResourceConstants}.
322             * @throws PortalException if a portal exception occurred
323             * @throws SystemException if a system exception occurred
324             */
325            public void deleteResource(AuditedModel auditedModel, int scope)
326                    throws PortalException, SystemException {
327    
328                    deleteResource(
329                            auditedModel.getCompanyId(), auditedModel.getModelClassName(),
330                            scope, String.valueOf(auditedModel.getPrimaryKeyObj()),
331                            getPermissionedModel(auditedModel));
332            }
333    
334            /**
335             * Deletes the resource matching the primary key at the scope.
336             *
337             * @param  companyId the primary key of the portal instance
338             * @param  name the resource's name, which should be a portlet ID if the
339             *         resource is a portlet or the resource's class name otherwise
340             * @param  scope the scope of the resource. For more information see {@link
341             *         com.liferay.portal.model.ResourceConstants}.
342             * @param  primKey the primary key of the resource instance
343             * @throws PortalException if a portal exception occurred
344             * @throws SystemException if a system exception occurred
345             */
346            public void deleteResource(
347                            long companyId, String name, int scope, long primKey)
348                    throws PortalException, SystemException {
349    
350                    deleteResource(companyId, name, scope, String.valueOf(primKey), null);
351            }
352    
353            /**
354             * Deletes the resource matching the primary key at the scope.
355             *
356             * @param  companyId the primary key of the portal instance
357             * @param  name the resource's name, which should be a portlet ID if the
358             *         resource is a portlet or the resource's class name otherwise
359             * @param  scope the scope of the resource. For more information see {@link
360             *         com.liferay.portal.model.ResourceConstants}.
361             * @param  primKey the primary key string of the resource instance
362             * @throws PortalException if a portal exception occurred
363             * @throws SystemException if a system exception occurred
364             */
365            public void deleteResource(
366                            long companyId, String name, int scope, String primKey)
367                    throws PortalException, SystemException {
368    
369                    deleteResource(companyId, name, scope, primKey, null);
370            }
371    
372            /**
373             * Returns a new resource with the name and primary key at the scope.
374             *
375             * @param  companyId the primary key of the portal instance
376             * @param  name a name for the resource, which should be a portlet ID if the
377             *         resource is a portlet or the resource's class name otherwise
378             * @param  scope the scope of the resource. For more information see {@link
379             *         com.liferay.portal.model.ResourceConstants}.
380             * @param  primKey the primary key string of the resource
381             * @return the new resource
382             */
383            public Resource getResource(
384                    long companyId, String name, int scope, String primKey) {
385    
386                    Resource resource = new ResourceImpl();
387    
388                    resource.setCompanyId(companyId);
389                    resource.setName(name);
390                    resource.setScope(scope);
391                    resource.setPrimKey(primKey);
392    
393                    return resource;
394            }
395    
396            /**
397             * Returns <code>true</code> if the roles have permission to perform the
398             * action on the resources.
399             *
400             * @param  userId the primary key of the user performing the permission
401             *         check
402             * @param  resourceId the primary key of the resource, typically the scope
403             *         group ID representing the scope in which the permission check is
404             *         being performed
405             * @param  resources the resources for which permissions are to be checked
406             * @param  actionId the primary key of the action to be performed on the
407             *         resources
408             * @param  roleIds the primary keys of the roles
409             * @return <code>true</code> if the roles have permission to perform the
410             *         action on the resources;<code>false</code> otherwise
411             * @throws PortalException if any one of the roles with the primary keys
412             *         could not be found or if a resource action with the action ID
413             *         could not be found
414             * @throws SystemException if a system exception occurred
415             */
416            public boolean hasUserPermissions(
417                            long userId, long resourceId, List<Resource> resources,
418                            String actionId, long[] roleIds)
419                    throws PortalException, SystemException {
420    
421                    StopWatch stopWatch = null;
422    
423                    if (_log.isDebugEnabled()) {
424                            stopWatch = new StopWatch();
425    
426                            stopWatch.start();
427                    }
428    
429                    int block = 1;
430    
431                    boolean hasUserPermissions =
432                            resourcePermissionLocalService.hasResourcePermission(
433                                    resources, roleIds, actionId);
434    
435                    logHasUserPermissions(userId, resourceId, actionId, stopWatch, block++);
436    
437                    return hasUserPermissions;
438            }
439    
440            /**
441             * Updates the resources for the model, replacing their group and guest
442             * permissions with new ones from the service context.
443             *
444             * @param  auditedModel the model associated with the resources
445             * @param  serviceContext the service context to be applied. Can set group
446             *         and guest permissions.
447             * @throws PortalException if a portal exception occurred
448             * @throws SystemException if a system exception occurred
449             */
450            public void updateModelResources(
451                            AuditedModel auditedModel, ServiceContext serviceContext)
452                    throws PortalException, SystemException {
453    
454                    updateResources(
455                            auditedModel.getCompanyId(), getGroupId(auditedModel),
456                            auditedModel.getModelClassName(),
457                            String.valueOf(auditedModel.getPrimaryKeyObj()),
458                            serviceContext.getGroupPermissions(),
459                            serviceContext.getGuestPermissions(),
460                            getPermissionedModel(auditedModel));
461            }
462    
463            /**
464             * Updates resources matching the group, name, and primary key at the
465             * individual scope, setting new group and guest permissions.
466             *
467             * @param  companyId the primary key of the portal instance
468             * @param  groupId the primary key of the group
469             * @param  name the resource's name, which should be a portlet ID if the
470             *         resource is a portlet or the resource's class name otherwise
471             * @param  primKey the primary key of the resource instance
472             * @param  groupPermissions the group permissions to be applied
473             * @param  guestPermissions the guest permissions to be applied
474             * @throws PortalException if a portal exception occurred
475             * @throws SystemException if a system exception occurred
476             */
477            public void updateResources(
478                            long companyId, long groupId, String name, long primKey,
479                            String[] groupPermissions, String[] guestPermissions)
480                    throws PortalException, SystemException {
481    
482                    updateResources(
483                            companyId, groupId, name, String.valueOf(primKey), groupPermissions,
484                            guestPermissions, null);
485            }
486    
487            /**
488             * Updates resources matching the group, name, and primary key string at the
489             * individual scope, setting new group and guest permissions.
490             *
491             * @param  companyId the primary key of the portal instance
492             * @param  groupId the primary key of the group
493             * @param  name the resource's name, which should be a portlet ID if the
494             *         resource is a portlet or the resource's class name otherwise
495             * @param  primKey the primary key string of the resource instance
496             * @param  groupPermissions the group permissions to be applied
497             * @param  guestPermissions the guest permissions to be applied
498             * @throws PortalException if a portal exception occurred
499             * @throws SystemException if a system exception occurred
500             */
501            public void updateResources(
502                            long companyId, long groupId, String name, String primKey,
503                            String[] groupPermissions, String[] guestPermissions)
504                    throws PortalException, SystemException {
505    
506                    updateResources(
507                            companyId, groupId, name, primKey, groupPermissions,
508                            guestPermissions, null);
509            }
510    
511            /**
512             * Updates resources matching the name, primary key string and scope,
513             * replacing the primary key of their resource permissions with the new
514             * primary key.
515             *
516             * @param  companyId the primary key of the portal instance
517             * @param  name the resource's name, which should be a portlet ID if the
518             *         resource is a portlet or the resource's class name otherwise
519             * @param  scope the scope of the resource. For more information see {@link
520             *         com.liferay.portal.model.ResourceConstants}.
521             * @param  primKey the primary key string of the resource instance
522             * @param  newPrimKey the new primary key string of the resource
523             * @throws SystemException if a system exception occurred
524             */
525            public void updateResources(
526                            long companyId, String name, int scope, String primKey,
527                            String newPrimKey)
528                    throws SystemException {
529    
530                    if (resourceBlockLocalService.isSupported(name)) {
531    
532                            // Assuming that this method is used when the primary key of an
533                            // existing record is changed, then nothing needs to happen here, as
534                            // it should still have its resource block ID.
535    
536                    }
537                    else {
538                            updateResourcePermissions(
539                                    companyId, name, scope, primKey, newPrimKey);
540                    }
541            }
542    
543            protected void addGroupPermissions(
544                            long companyId, long groupId, long userId, String name,
545                            Resource resource, boolean portletActions,
546                            PermissionedModel permissionedModel)
547                    throws PortalException, SystemException {
548    
549                    List<String> actions = null;
550    
551                    if (portletActions) {
552                            actions = ResourceActionsUtil.getPortletResourceGroupDefaultActions(
553                                    name);
554                    }
555                    else {
556                            actions = ResourceActionsUtil.getModelResourceGroupDefaultActions(
557                                    name);
558                    }
559    
560                    String[] actionIds = actions.toArray(new String[actions.size()]);
561    
562                    if (resourceBlockLocalService.isSupported(name)) {
563                            addGroupPermissionsBlocks(
564                                    groupId, resource, actions, permissionedModel);
565                    }
566                    else {
567                            addGroupPermissions(groupId, resource, actionIds);
568                    }
569            }
570    
571            protected void addGroupPermissions(
572                            long groupId, Resource resource, String[] actionIds)
573                    throws PortalException, SystemException {
574    
575                    Role role = roleLocalService.getDefaultGroupRole(groupId);
576    
577                    resourcePermissionLocalService.setResourcePermissions(
578                            resource.getCompanyId(), resource.getName(), resource.getScope(),
579                            resource.getPrimKey(), role.getRoleId(), actionIds);
580            }
581    
582            protected void addGroupPermissionsBlocks(
583                            long groupId, Resource resource, List<String> actionIds,
584                            PermissionedModel permissionedModel)
585                    throws PortalException, SystemException {
586    
587                    if (permissionedModel == null) {
588                            throw new IllegalArgumentException("Permissioned model is null");
589                    }
590    
591                    // Scope is assumed to always be individual
592    
593                    Role role = roleLocalService.getDefaultGroupRole(groupId);
594    
595                    resourceBlockLocalService.setIndividualScopePermissions(
596                            resource.getCompanyId(), groupId, resource.getName(),
597                            permissionedModel, role.getRoleId(), actionIds);
598            }
599    
600            protected void addGuestPermissions(
601                            long companyId, long groupId, long userId, String name,
602                            Resource resource, boolean portletActions,
603                            PermissionedModel permissionedModel)
604                    throws PortalException, SystemException {
605    
606                    List<String> actions = null;
607    
608                    if (portletActions) {
609                            actions = ResourceActionsUtil.getPortletResourceGuestDefaultActions(
610                                    name);
611                    }
612                    else {
613                            actions = ResourceActionsUtil.getModelResourceGuestDefaultActions(
614                                    name);
615                    }
616    
617                    String[] actionIds = actions.toArray(new String[actions.size()]);
618    
619                    if (resourceBlockLocalService.isSupported(name)) {
620                            addGuestPermissionsBlocks(
621                                    companyId, groupId, resource, actions, permissionedModel);
622                    }
623                    else {
624                            addGuestPermissions(companyId, resource, actionIds);
625                    }
626            }
627    
628            protected void addGuestPermissions(
629                            long companyId, Resource resource, String[] actionIds)
630                    throws PortalException, SystemException {
631    
632                    Role guestRole = roleLocalService.getRole(
633                            companyId, RoleConstants.GUEST);
634    
635                    resourcePermissionLocalService.setResourcePermissions(
636                            resource.getCompanyId(), resource.getName(), resource.getScope(),
637                            resource.getPrimKey(), guestRole.getRoleId(), actionIds);
638            }
639    
640            protected void addGuestPermissionsBlocks(
641                            long companyId, long groupId, Resource resource,
642                            List<String> actionIds, PermissionedModel permissionedModel)
643                    throws PortalException, SystemException {
644    
645                    if (permissionedModel == null) {
646                            throw new IllegalArgumentException("Permissioned model is null");
647                    }
648    
649                    // Scope is assumed to always be individual
650    
651                    Role guestRole = roleLocalService.getRole(
652                            companyId, RoleConstants.GUEST);
653    
654                    resourceBlockLocalService.setIndividualScopePermissions(
655                            resource.getCompanyId(), groupId, resource.getName(),
656                            permissionedModel, guestRole.getRoleId(), actionIds);
657            }
658    
659            protected void addModelResources(
660                            long companyId, long groupId, long userId, Resource resource,
661                            String[] groupPermissions, String[] guestPermissions,
662                            PermissionedModel permissionedModel)
663                    throws PortalException, SystemException {
664    
665                    // Owner permissions
666    
667                    Role ownerRole = roleLocalService.getRole(
668                            companyId, RoleConstants.OWNER);
669    
670                    List<String> ownerActionIds =
671                            ResourceActionsUtil.getModelResourceActions(resource.getName());
672    
673                    ownerActionIds = ListUtil.copy(ownerActionIds);
674    
675                    filterOwnerActions(resource.getName(), ownerActionIds);
676    
677                    String[] ownerPermissions = ownerActionIds.toArray(
678                            new String[ownerActionIds.size()]);
679    
680                    // Group permissions
681    
682                    Role defaultGroupRole = null;
683    
684                    if (groupId > 0) {
685                            defaultGroupRole = roleLocalService.getDefaultGroupRole(groupId);
686    
687                            if (groupPermissions == null) {
688                                    groupPermissions = new String[0];
689                            }
690                    }
691    
692                    // Guest permissions
693    
694                    Role guestRole = roleLocalService.getRole(
695                            companyId, RoleConstants.GUEST);
696    
697                    if (guestPermissions == null) {
698                            guestPermissions = new String[0];
699                    }
700    
701                    if (resourceBlockLocalService.isSupported(resource.getName())) {
702    
703                            if (permissionedModel == null) {
704                                    throw new IllegalArgumentException(
705                                            "Permissioned model is null");
706                            }
707    
708                            // Scope is assumed to always be individual
709    
710                            resourceBlockLocalService.setIndividualScopePermissions(
711                                    resource.getCompanyId(), groupId, resource.getName(),
712                                    permissionedModel, ownerRole.getRoleId(), ownerActionIds);
713    
714                            if (groupId > 0) {
715                                    resourceBlockLocalService.setIndividualScopePermissions(
716                                            resource.getCompanyId(), groupId, resource.getName(),
717                                            permissionedModel, defaultGroupRole.getRoleId(),
718                                            Arrays.asList(groupPermissions));
719                            }
720    
721                            resourceBlockLocalService.setIndividualScopePermissions(
722                                    resource.getCompanyId(), groupId, resource.getName(),
723                                    permissionedModel, guestRole.getRoleId(),
724                                    Arrays.asList(guestPermissions));
725                    }
726                    else {
727                            resourcePermissionLocalService.setOwnerResourcePermissions(
728                                    resource.getCompanyId(), resource.getName(),
729                                    resource.getScope(), resource.getPrimKey(),
730                                    ownerRole.getRoleId(), userId, ownerPermissions);
731    
732                            if (groupId > 0) {
733                                    resourcePermissionLocalService.setResourcePermissions(
734                                            resource.getCompanyId(), resource.getName(),
735                                            resource.getScope(), resource.getPrimKey(),
736                                            defaultGroupRole.getRoleId(), groupPermissions);
737                            }
738    
739                            resourcePermissionLocalService.setResourcePermissions(
740                                    resource.getCompanyId(), resource.getName(),
741                                    resource.getScope(), resource.getPrimKey(),
742                                    guestRole.getRoleId(), guestPermissions);
743                    }
744            }
745    
746            protected void addModelResources(
747                            long companyId, long groupId, long userId, String name,
748                            String primKey, String[] groupPermissions,
749                            String[] guestPermissions, PermissionedModel permissionedModel)
750                    throws PortalException, SystemException {
751    
752                    if (!PermissionThreadLocal.isAddResource()) {
753                            return;
754                    }
755    
756                    validate(name, false);
757    
758                    if (primKey == null) {
759                            return;
760                    }
761    
762                    // Individual
763    
764                    Resource resource = getResource(
765                            companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
766    
767                    // Permissions
768    
769                    boolean flushEnabled = PermissionThreadLocal.isFlushEnabled();
770    
771                    PermissionThreadLocal.setIndexEnabled(false);
772    
773                    try {
774                            addModelResources(
775                                    companyId, groupId, userId, resource, groupPermissions,
776                                    guestPermissions, permissionedModel);
777                    }
778                    finally {
779                            PermissionThreadLocal.setIndexEnabled(flushEnabled);
780    
781                            PermissionCacheUtil.clearCache();
782    
783                            SearchEngineUtil.updatePermissionFields(name, primKey);
784                    }
785            }
786    
787            protected void addResources(
788                            long companyId, long groupId, long userId, Resource resource,
789                            boolean portletActions, PermissionedModel permissionedModel)
790                    throws PortalException, SystemException {
791    
792                    List<String> actionIds = null;
793    
794                    if (portletActions) {
795                            actionIds = ResourceActionsUtil.getPortletResourceActions(
796                                    resource.getName());
797                    }
798                    else {
799                            actionIds = ResourceActionsUtil.getModelResourceActions(
800                                    resource.getName());
801    
802                            actionIds = ListUtil.copy(actionIds);
803    
804                            filterOwnerActions(resource.getName(), actionIds);
805                    }
806    
807                    Role role = roleLocalService.getRole(companyId, RoleConstants.OWNER);
808    
809                    if (resourceBlockLocalService.isSupported(resource.getName())) {
810                            if (permissionedModel == null) {
811                                    throw new IllegalArgumentException(
812                                            "Permissioned model is null");
813                            }
814    
815                            // Scope is assumed to always be individual
816    
817                            resourceBlockLocalService.setIndividualScopePermissions(
818                                    resource.getCompanyId(), groupId, resource.getName(),
819                                    permissionedModel, role.getRoleId(), actionIds);
820                    }
821                    else {
822                            resourcePermissionLocalService.setOwnerResourcePermissions(
823                                    resource.getCompanyId(), resource.getName(),
824                                    resource.getScope(), resource.getPrimKey(), role.getRoleId(),
825                                    userId, actionIds.toArray(new String[actionIds.size()]));
826                    }
827            }
828    
829            protected void addResources(
830                            long companyId, long groupId, long userId, String name,
831                            String primKey, boolean portletActions, boolean addGroupPermissions,
832                            boolean addGuestPermissions, PermissionedModel permissionedModel)
833                    throws PortalException, SystemException {
834    
835                    if (!PermissionThreadLocal.isAddResource()) {
836                            return;
837                    }
838    
839                    validate(name, portletActions);
840    
841                    if (primKey == null) {
842                            return;
843                    }
844    
845                    // Individual
846    
847                    Resource resource = getResource(
848                            companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
849    
850                    // Permissions
851    
852                    boolean flushEnabled = PermissionThreadLocal.isFlushEnabled();
853    
854                    PermissionThreadLocal.setIndexEnabled(false);
855    
856                    List<ResourcePermission> resourcePermissions =
857                            resourcePermissionPersistence.findByC_N_S_P(
858                                    companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
859    
860                    ResourcePermissionsThreadLocal.setResourcePermissions(
861                            resourcePermissions);
862    
863                    try {
864                            addResources(
865                                    companyId, groupId, userId, resource, portletActions,
866                                    permissionedModel);
867    
868                            // Group permissions
869    
870                            if ((groupId > 0) && addGroupPermissions) {
871                                    addGroupPermissions(
872                                            companyId, groupId, userId, name, resource, portletActions,
873                                            permissionedModel);
874                            }
875    
876                            // Guest permissions
877    
878                            if (addGuestPermissions) {
879    
880                                    // Don't add guest permissions when you've already added group
881                                    // permissions and the given group is the guest group.
882    
883                                    addGuestPermissions(
884                                            companyId, groupId, userId, name, resource, portletActions,
885                                            permissionedModel);
886                            }
887                    }
888                    finally {
889                            ResourcePermissionsThreadLocal.setResourcePermissions(null);
890    
891                            PermissionThreadLocal.setIndexEnabled(flushEnabled);
892    
893                            PermissionCacheUtil.clearCache();
894    
895                            SearchEngineUtil.updatePermissionFields(name, primKey);
896                    }
897            }
898    
899            protected void deleteResource(
900                            long companyId, String name, int scope, String primKey,
901                            PermissionedModel permissionedModel)
902                    throws PortalException, SystemException {
903    
904                    if (resourceBlockLocalService.isSupported(name)) {
905                            if (permissionedModel == null) {
906                                    throw new IllegalArgumentException(
907                                            "Permissioned model is null");
908                            }
909    
910                            resourceBlockLocalService.releasePermissionedModelResourceBlock(
911                                    permissionedModel);
912    
913                            return;
914                    }
915    
916                    resourcePermissionLocalService.deleteResourcePermissions(
917                            companyId, name, scope, primKey);
918            }
919    
920            protected void filterOwnerActions(String name, List<String> actionIds) {
921                    List<String> defaultOwnerActions =
922                            ResourceActionsUtil.getModelResourceOwnerDefaultActions(name);
923    
924                    if (defaultOwnerActions.isEmpty()) {
925                            return;
926                    }
927    
928                    Iterator<String> itr = actionIds.iterator();
929    
930                    while (itr.hasNext()) {
931                            String actionId = itr.next();
932    
933                            if (!defaultOwnerActions.contains(actionId)) {
934                                    itr.remove();
935                            }
936                    }
937            }
938    
939            protected long getGroupId(AuditedModel auditedModel) {
940                    long groupId = 0;
941    
942                    if (auditedModel instanceof GroupedModel) {
943                            GroupedModel groupedModel = (GroupedModel)auditedModel;
944    
945                            groupId = BeanPropertiesUtil.getLongSilent(
946                                    groupedModel, "resourceGroupId", groupedModel.getGroupId());
947                    }
948    
949                    return groupId;
950            }
951    
952            protected PermissionedModel getPermissionedModel(
953                    AuditedModel auditedModel) {
954    
955                    PermissionedModel permissionedModel = null;
956    
957                    if (auditedModel instanceof PermissionedModel) {
958                            permissionedModel = (PermissionedModel)auditedModel;
959                    }
960    
961                    return permissionedModel;
962            }
963    
964            protected void logHasUserPermissions(
965                    long userId, long resourceId, String actionId, StopWatch stopWatch,
966                    int block) {
967    
968                    if (!_log.isDebugEnabled()) {
969                            return;
970                    }
971    
972                    _log.debug(
973                            "Checking user permissions block " + block + " for " + userId +
974                                    " " + resourceId + " " + actionId + " takes " +
975                                            stopWatch.getTime() + " ms");
976            }
977    
978            protected void updateResourceBlocks(
979                            long companyId, long groupId, Resource resource,
980                            String[] groupPermissions, String[] guestPermissions,
981                            PermissionedModel permissionedModel)
982                    throws PortalException, SystemException {
983    
984                    if (permissionedModel == null) {
985                            throw new IllegalArgumentException("Permissioned model is null");
986                    }
987    
988                    // Scope is assumed to always be individual
989    
990                    Role role = roleLocalService.getDefaultGroupRole(groupId);
991    
992                    resourceBlockLocalService.setIndividualScopePermissions(
993                            companyId, groupId, resource.getName(), permissionedModel,
994                            role.getRoleId(), Arrays.asList(groupPermissions));
995    
996                    role = roleLocalService.getRole(companyId, RoleConstants.GUEST);
997    
998                    resourceBlockLocalService.setIndividualScopePermissions(
999                            companyId, groupId, resource.getName(), permissionedModel,
1000                            role.getRoleId(), Arrays.asList(guestPermissions));
1001            }
1002    
1003            protected void updateResourcePermissions(
1004                            long companyId, long groupId, Resource resource,
1005                            String[] groupPermissions, String[] guestPermissions)
1006                    throws PortalException, SystemException {
1007    
1008                    Role role = roleLocalService.getDefaultGroupRole(groupId);
1009    
1010                    resourcePermissionLocalService.setResourcePermissions(
1011                            resource.getCompanyId(), resource.getName(), resource.getScope(),
1012                            resource.getPrimKey(), role.getRoleId(), groupPermissions);
1013    
1014                    role = roleLocalService.getRole(companyId, RoleConstants.GUEST);
1015    
1016                    resourcePermissionLocalService.setResourcePermissions(
1017                            resource.getCompanyId(), resource.getName(), resource.getScope(),
1018                            resource.getPrimKey(), role.getRoleId(), guestPermissions);
1019            }
1020    
1021            protected void updateResourcePermissions(
1022                            long companyId, String name, int scope, String primKey,
1023                            String newPrimKey)
1024                    throws SystemException {
1025    
1026                    List<ResourcePermission> resourcePermissions =
1027                            resourcePermissionLocalService.getResourcePermissions(
1028                                    companyId, name, scope, primKey);
1029    
1030                    for (ResourcePermission resourcePermission : resourcePermissions) {
1031                            resourcePermission.setPrimKey(newPrimKey);
1032    
1033                            resourcePermissionPersistence.update(resourcePermission);
1034                    }
1035            }
1036    
1037            protected void updateResources(
1038                            long companyId, long groupId, String name, String primKey,
1039                            String[] groupPermissions, String[] guestPermissions,
1040                            PermissionedModel permissionedModel)
1041                    throws PortalException, SystemException {
1042    
1043                    Resource resource = getResource(
1044                            companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
1045    
1046                    if (groupPermissions == null) {
1047                            groupPermissions = new String[0];
1048                    }
1049    
1050                    if (guestPermissions == null) {
1051                            guestPermissions = new String[0];
1052                    }
1053    
1054                    if (resourceBlockLocalService.isSupported(name)) {
1055                            updateResourceBlocks(
1056                                    companyId, groupId, resource, groupPermissions,
1057                                    guestPermissions, permissionedModel);
1058                    }
1059                    else {
1060                            updateResourcePermissions(
1061                                    companyId, groupId, resource, groupPermissions,
1062                                    guestPermissions);
1063                    }
1064            }
1065    
1066            protected void validate(String name, boolean portletActions)
1067                    throws PortalException {
1068    
1069                    List<String> actions = null;
1070    
1071                    if (portletActions) {
1072                            actions = ResourceActionsUtil.getPortletResourceActions(name);
1073                    }
1074                    else {
1075                            actions = ResourceActionsUtil.getModelResourceActions(name);
1076                    }
1077    
1078                    if (actions.size() == 0) {
1079                            throw new ResourceActionsException(
1080                                    "There are no actions associated with the resource " + name);
1081                    }
1082            }
1083    
1084            private static Log _log = LogFactoryUtil.getLog(
1085                    ResourceLocalServiceImpl.class);
1086    
1087    }