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