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.NoSuchGroupException;
018    import com.liferay.portal.kernel.dao.orm.QueryUtil;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.staging.StagingUtil;
022    import com.liferay.portal.kernel.util.ArrayUtil;
023    import com.liferay.portal.kernel.util.ListUtil;
024    import com.liferay.portal.kernel.util.MapUtil;
025    import com.liferay.portal.kernel.util.UnicodeProperties;
026    import com.liferay.portal.kernel.util.UniqueList;
027    import com.liferay.portal.model.Group;
028    import com.liferay.portal.model.GroupConstants;
029    import com.liferay.portal.model.Organization;
030    import com.liferay.portal.model.Portlet;
031    import com.liferay.portal.model.User;
032    import com.liferay.portal.model.UserGroup;
033    import com.liferay.portal.security.auth.PrincipalException;
034    import com.liferay.portal.security.membershippolicy.SiteMembershipPolicyUtil;
035    import com.liferay.portal.security.permission.ActionKeys;
036    import com.liferay.portal.security.permission.PermissionChecker;
037    import com.liferay.portal.security.permission.PermissionCheckerFactoryUtil;
038    import com.liferay.portal.service.ServiceContext;
039    import com.liferay.portal.service.base.GroupServiceBaseImpl;
040    import com.liferay.portal.service.permission.GroupPermissionUtil;
041    import com.liferay.portal.service.permission.PortalPermissionUtil;
042    import com.liferay.portal.service.permission.PortletPermissionUtil;
043    import com.liferay.portal.service.permission.RolePermissionUtil;
044    import com.liferay.portal.service.permission.UserPermissionUtil;
045    import com.liferay.portal.util.PropsValues;
046    import com.liferay.portlet.asset.model.AssetCategory;
047    import com.liferay.portlet.asset.model.AssetTag;
048    import com.liferay.portlet.expando.model.ExpandoBridge;
049    
050    import java.io.Serializable;
051    
052    import java.util.ArrayList;
053    import java.util.Collection;
054    import java.util.Collections;
055    import java.util.Iterator;
056    import java.util.LinkedHashMap;
057    import java.util.List;
058    import java.util.Map;
059    
060    /**
061     * Provides the remote service for accessing, adding, deleting, and updating
062     * groups. Its methods include permission checks. Groups are mostly used in
063     * Liferay as a resource container for permissioning and content scoping
064     * purposes.
065     *
066     * @author Brian Wing Shun Chan
067     * @see    com.liferay.portal.service.impl.GroupLocalServiceImpl
068     */
069    public class GroupServiceImpl extends GroupServiceBaseImpl {
070    
071            /**
072             * Adds a group.
073             *
074             * @param  parentGroupId the primary key of the parent group
075             * @param  liveGroupId the primary key of the live group
076             * @param  name the entity's name
077             * @param  description the group's description (optionally
078             *         <code>null</code>)
079             * @param  type the group's type. For more information see {@link
080             *         com.liferay.portal.model.GroupConstants}
081             * @param  friendlyURL the group's friendlyURL (optionally
082             *         <code>null</code>)
083             * @param  site whether the group is to be associated with a main site
084             * @param  active whether the group is active
085             * @param  serviceContext the service context to be applied (optionally
086             *         <code>null</code>). Can set the asset category IDs and asset tag
087             *         names for the group, and can set whether the group is for staging
088             * @return the group
089             * @throws PortalException if the user did not have permission to add the
090             *         group, if a creator could not be found, if the group's
091             *         information was invalid, if a layout could not be found, or if a
092             *         valid friendly URL could not be created for the group
093             * @throws SystemException if a system exception occurred
094             */
095            @Override
096            public Group addGroup(
097                            long parentGroupId, long liveGroupId, String name,
098                            String description, int type, boolean manualMembership,
099                            int membershipRestriction, String friendlyURL, boolean site,
100                            boolean active, ServiceContext serviceContext)
101                    throws PortalException, SystemException {
102    
103                    if (parentGroupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
104                            PortalPermissionUtil.check(
105                                    getPermissionChecker(), ActionKeys.ADD_COMMUNITY);
106                    }
107                    else {
108                            GroupPermissionUtil.check(
109                                    getPermissionChecker(), parentGroupId,
110                                    ActionKeys.ADD_COMMUNITY);
111                    }
112    
113                    Group group = groupLocalService.addGroup(
114                            getUserId(), parentGroupId, null, 0, liveGroupId, name, description,
115                            type, manualMembership, membershipRestriction, friendlyURL, site,
116                            active, serviceContext);
117    
118                    if (site) {
119                            SiteMembershipPolicyUtil.verifyPolicy(group);
120                    }
121    
122                    return group;
123            }
124    
125            /**
126             * Adds the group using the group default live group ID.
127             *
128             * @param      parentGroupId the primary key of the parent group
129             * @param      name the entity's name
130             * @param      description the group's description (optionally
131             *             <code>null</code>)
132             * @param      type the group's type. For more information see {@link
133             *             com.liferay.portal.model.GroupConstants}
134             * @param      friendlyURL the group's friendlyURL
135             * @param      site whether the group is to be associated with a main site
136             * @param      active whether the group is active
137             * @param      serviceContext the service context to be applied (optionally
138             *             <code>null</code>). Can set asset category IDs and asset tag
139             *             names for the group, and can set whether the group is for
140             *             staging
141             * @return     the group
142             * @throws     PortalException if the user did not have permission to add
143             *             the group, if a creator could not be found, if the group's
144             *             information was invalid, if a layout could not be found, or
145             *             if a valid friendly URL could not be created for the group
146             * @throws     SystemException if a system exception occurred
147             * @deprecated As of 6.2.0, replaced by {@link #addGroup(long, long, String,
148             *             String, int, boolean, int, String, boolean, boolean,
149             *             ServiceContext)}
150             */
151            @Override
152            public Group addGroup(
153                            long parentGroupId, String name, String description, int type,
154                            String friendlyURL, boolean site, boolean active,
155                            ServiceContext serviceContext)
156                    throws PortalException, SystemException {
157    
158                    return addGroup(
159                            parentGroupId, GroupConstants.DEFAULT_LIVE_GROUP_ID, name,
160                            description, type, true,
161                            GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION, friendlyURL, site,
162                            active, serviceContext);
163            }
164    
165            /**
166             * @deprecated As of 6.2.0, replaced by {@link #addGroup(long, String,
167             *             String, int, String, boolean, boolean, ServiceContext)}
168             */
169            @Override
170            public Group addGroup(
171                            String name, String description, int type, String friendlyURL,
172                            boolean site, boolean active, ServiceContext serviceContext)
173                    throws PortalException, SystemException {
174    
175                    return addGroup(
176                            GroupConstants.DEFAULT_PARENT_GROUP_ID, name, description, type,
177                            friendlyURL, site, active, serviceContext);
178            }
179    
180            /**
181             * Adds the groups to the role.
182             *
183             * @param  roleId the primary key of the role
184             * @param  groupIds the primary keys of the groups
185             * @throws PortalException if the user did not have permission to update the
186             *         role
187             * @throws SystemException if a system exception occurred
188             */
189            @Override
190            public void addRoleGroups(long roleId, long[] groupIds)
191                    throws PortalException, SystemException {
192    
193                    RolePermissionUtil.check(
194                            getPermissionChecker(), roleId, ActionKeys.UPDATE);
195    
196                    groupLocalService.addRoleGroups(roleId, groupIds);
197            }
198    
199            /**
200             * Checks that the current user is permitted to use the group for Remote
201             * Staging.
202             *
203             * @param  groupId the primary key of the group
204             * @throws PortalException if a group with the primary key could not be
205             *         found, if the current user did not have permission to view the
206             *         group, or if the group's company was different from the current
207             *         user's company
208             * @throws SystemException if a system exception occurred
209             */
210            @Override
211            public void checkRemoteStagingGroup(long groupId)
212                    throws PortalException, SystemException {
213    
214                    Group group = getGroup(groupId);
215    
216                    PermissionChecker permissionChecker = getPermissionChecker();
217    
218                    if (group.getCompanyId() != permissionChecker.getCompanyId()) {
219                            throw new NoSuchGroupException(
220                                    "Group " + groupId + " does not belong in company " +
221                                            permissionChecker.getCompanyId());
222                    }
223            }
224    
225            /**
226             * Deletes the group.
227             *
228             * <p>
229             * The group is unstaged and its assets and resources including layouts,
230             * membership requests, subscriptions, teams, blogs, bookmarks, calendar
231             * events, image gallery, journals, message boards, polls, shopping related
232             * entities, software catalog, and wikis are also deleted.
233             * </p>
234             *
235             * @param  groupId the primary key of the group
236             * @throws PortalException if the user did not have permission to delete the
237             *         group or its assets or resources, if a group with the primary key
238             *         could not be found, or if the group was a system group
239             * @throws SystemException if a system exception occurred
240             */
241            @Override
242            public void deleteGroup(long groupId)
243                    throws PortalException, SystemException {
244    
245                    GroupPermissionUtil.check(
246                            getPermissionChecker(), groupId, ActionKeys.DELETE);
247    
248                    groupLocalService.deleteGroup(groupId);
249            }
250    
251            @Override
252            public void disableStaging(long groupId)
253                    throws PortalException, SystemException {
254    
255                    Group group = groupLocalService.getGroup(groupId);
256    
257                    GroupPermissionUtil.check(
258                            getPermissionChecker(), group, ActionKeys.UPDATE);
259    
260                    groupLocalService.disableStaging(groupId);
261            }
262    
263            @Override
264            public void enableStaging(long groupId)
265                    throws PortalException, SystemException {
266    
267                    Group group = groupLocalService.getGroup(groupId);
268    
269                    GroupPermissionUtil.check(
270                            getPermissionChecker(), group, ActionKeys.UPDATE);
271    
272                    groupLocalService.enableStaging(groupId);
273            }
274    
275            /**
276             * Returns the company group.
277             *
278             * @param  companyId the primary key of the company
279             * @return the group associated with the company
280             * @throws PortalException if a matching group could not be found
281             * @throws SystemException if a system exception occurred
282             */
283            @Override
284            public Group getCompanyGroup(long companyId)
285                    throws PortalException, SystemException {
286    
287                    Group group = groupLocalService.getCompanyGroup(companyId);
288    
289                    GroupPermissionUtil.check(
290                            getPermissionChecker(), group.getGroupId(), ActionKeys.VIEW);
291    
292                    return group;
293            }
294    
295            /**
296             * Returns the group with the primary key.
297             *
298             * @param  groupId the primary key of the group
299             * @return the group with the primary key
300             * @throws PortalException if a group with the primary key could not be
301             *         found or if the current user did not have permission to view the
302             *         group
303             * @throws SystemException if a system exception occurred
304             */
305            @Override
306            public Group getGroup(long groupId)
307                    throws PortalException, SystemException {
308    
309                    GroupPermissionUtil.check(
310                            getPermissionChecker(), groupId, ActionKeys.VIEW);
311    
312                    return groupLocalService.getGroup(groupId);
313            }
314    
315            /**
316             * Returns the group with the name.
317             *
318             * @param  companyId the primary key of the company
319             * @param  name the group's name
320             * @return the group with the name
321             * @throws PortalException if a matching group could not be found or if the
322             *         current user did not have permission to view the group
323             * @throws SystemException if a system exception occurred
324             */
325            @Override
326            public Group getGroup(long companyId, String name)
327                    throws PortalException, SystemException {
328    
329                    Group group = groupLocalService.getGroup(companyId, name);
330    
331                    GroupPermissionUtil.check(
332                            getPermissionChecker(), group.getGroupId(), ActionKeys.VIEW);
333    
334                    return group;
335            }
336    
337            /**
338             * Returns all the groups that are direct children of the parent group.
339             *
340             * @param  companyId the primary key of the company
341             * @param  parentGroupId the primary key of the parent group
342             * @param  site whether the group is to be associated with a main site
343             * @return the matching groups, or <code>null</code> if no matches were
344             *         found
345             * @throws PortalException if the user did not have permission to view the
346             *         group or if a portal exception occurred
347             * @throws SystemException if a system exception occurred
348             */
349            @Override
350            public List<Group> getGroups(
351                            long companyId, long parentGroupId, boolean site)
352                    throws PortalException, SystemException {
353    
354                    return filterGroups(
355                            groupLocalService.getGroups(companyId, parentGroupId, site));
356            }
357    
358            /**
359             * Returns a range of all the site groups for which the user has control
360             * panel access.
361             *
362             * @param  portlets the portlets to manage
363             * @param  max the upper bound of the range of groups to consider (not
364             *         inclusive)
365             * @return the range of site groups for which the user has Control Panel
366             *         access
367             * @throws PortalException if a portal exception occurred
368             * @throws SystemException if a system exception occurred
369             */
370            @Override
371            public List<Group> getManageableSiteGroups(
372                            Collection<Portlet> portlets, int max)
373                    throws PortalException, SystemException {
374    
375                    PermissionChecker permissionChecker = getPermissionChecker();
376    
377                    if (permissionChecker.isCompanyAdmin()) {
378                            LinkedHashMap<String, Object> params =
379                                    new LinkedHashMap<String, Object>();
380    
381                            params.put("site", Boolean.TRUE);
382    
383                            return groupLocalService.search(
384                                    permissionChecker.getCompanyId(), null, null, null, params,
385                                    true, 0, max);
386                    }
387    
388                    List<Group> groups = new UniqueList<Group>();
389    
390                    List<Group> userSitesGroups = getUserSitesGroups(null, max);
391    
392                    Iterator<Group> itr = userSitesGroups.iterator();
393    
394                    while (itr.hasNext()) {
395                            Group group = itr.next();
396    
397                            if (group.isSite() &&
398                                    PortletPermissionUtil.hasControlPanelAccessPermission(
399                                            permissionChecker, group.getGroupId(), portlets)) {
400    
401                                    groups.add(group);
402                            }
403                    }
404    
405                    return groups;
406            }
407    
408            /**
409             * Returns a range of all the site groups for which the user has control
410             * panel access.
411             *
412             * @param      portlets the portlets to manage
413             * @param      max the upper bound of the range of groups to consider (not
414             *             inclusive)
415             * @return     the range of site groups for which the user has Control Panel
416             *             access
417             * @throws     PortalException if a portal exception occurred
418             * @throws     SystemException if a system exception occurred
419             * @deprecated As of 6.2.0, replaced by {@link
420             *             #getManageableSiteGroups(Collection, int)}
421             */
422            @Override
423            public List<Group> getManageableSites(Collection<Portlet> portlets, int max)
424                    throws PortalException, SystemException {
425    
426                    return getManageableSiteGroups(portlets, max);
427            }
428    
429            /**
430             * Returns the groups associated with the organizations.
431             *
432             * @param  organizations the organizations
433             * @return the groups associated with the organizations
434             * @throws PortalException if a portal exception occurred
435             * @throws SystemException if a system exception occurred
436             */
437            @Override
438            public List<Group> getOrganizationsGroups(List<Organization> organizations)
439                    throws PortalException, SystemException {
440    
441                    List<Group> groups = groupLocalService.getOrganizationsGroups(
442                            organizations);
443    
444                    return filterGroups(groups);
445            }
446    
447            /**
448             * Returns the group associated with the user.
449             *
450             * @param  companyId the primary key of the company
451             * @param  userId the primary key of the user
452             * @return the group associated with the user
453             * @throws PortalException if a matching group could not be found or if the
454             *         current user did not have permission to view the group
455             * @throws SystemException if a system exception occurred
456             */
457            @Override
458            public Group getUserGroup(long companyId, long userId)
459                    throws PortalException, SystemException {
460    
461                    Group group = groupLocalService.getUserGroup(companyId, userId);
462    
463                    GroupPermissionUtil.check(
464                            getPermissionChecker(), group.getGroupId(), ActionKeys.VIEW);
465    
466                    return group;
467            }
468    
469            /**
470             * Returns the groups associated with the user groups.
471             *
472             * @param  userGroups the user groups
473             * @return the groups associated with the user groups
474             * @throws PortalException if any one of the user group's group could not be
475             *         found
476             * @throws SystemException if a system exception occurred
477             */
478            @Override
479            public List<Group> getUserGroupsGroups(List<UserGroup> userGroups)
480                    throws PortalException, SystemException {
481    
482                    List<Group> groups = groupLocalService.getUserGroupsGroups(userGroups);
483    
484                    return filterGroups(groups);
485            }
486    
487            /**
488             * Returns the range of all groups associated with the user's organization
489             * groups, including the ancestors of the organization groups, unless portal
490             * property <code>organizations.membership.strict</code> is set to
491             * <code>true</code>.
492             *
493             * <p>
494             * Useful when paginating results. Returns a maximum of <code>end -
495             * start</code> instances. <code>start</code> and <code>end</code> are not
496             * primary keys, they are indexes in the result set. Thus, <code>0</code>
497             * refers to the first result in the set. Setting both <code>start</code>
498             * and <code>end</code> to {@link
499             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
500             * result set.
501             * </p>
502             *
503             * @param  userId the primary key of the user
504             * @param  start the lower bound of the range of groups to consider
505             * @param  end the upper bound of the range of groups to consider (not
506             *         inclusive)
507             * @return the range of groups associated with the user's organizations
508             * @throws PortalException if a user with the primary key could not be found
509             *         or if another portal exception occurred
510             * @throws SystemException if a system exception occurred
511             */
512            @Override
513            public List<Group> getUserOrganizationsGroups(
514                            long userId, int start, int end)
515                    throws PortalException, SystemException {
516    
517                    List<Group> groups = groupLocalService.getUserOrganizationsGroups(
518                            userId, start, end);
519    
520                    return filterGroups(groups);
521            }
522    
523            /**
524             * @deprecated As of 6.2.0, replaced by {@link #getUserSitesGroups(long,
525             *             String[], boolean, int)}
526             */
527            @Override
528            public List<Group> getUserPlaces(
529                            long userId, String[] classNames, boolean includeControlPanel,
530                            int max)
531                    throws PortalException, SystemException {
532    
533                    return getUserSitesGroups(userId, classNames, includeControlPanel, max);
534            }
535    
536            /**
537             * Returns the user's groups &quot;sites&quot; associated with the group
538             * entity class names, including the Control Panel group if the user is
539             * permitted to view the Control Panel.
540             *
541             * <ul>
542             * <li>
543             * Class name &quot;User&quot; includes the user's layout set
544             * group.
545             * </li>
546             * <li>
547             * Class name &quot;Organization&quot; includes the user's
548             * immediate organization groups and inherited organization groups.
549             * </li>
550             * <li>
551             * Class name &quot;Group&quot; includes the user's immediate
552             * organization groups and site groups.
553             * </li>
554             * <li>
555             * A <code>classNames</code>
556             * value of <code>null</code> includes the user's layout set group,
557             * organization groups, inherited organization groups, and site groups.
558             * </li>
559             * </ul>
560             *
561             * @param      userId the primary key of the user
562             * @param      classNames the group entity class names (optionally
563             *             <code>null</code>). For more information see {@link
564             *             #getUserSitesGroups(long, String[], int)}
565             * @param      max the maximum number of groups to return
566             * @return     the user's groups &quot;sites&quot;
567             * @throws     PortalException if a portal exception occurred
568             * @throws     SystemException if a system exception occurred
569             * @deprecated As of 6.2.0, replaced by {@link #getUserSitesGroups(long,
570             *             String[], int)}
571             */
572            @Override
573            public List<Group> getUserPlaces(long userId, String[] classNames, int max)
574                    throws PortalException, SystemException {
575    
576                    return getUserSitesGroups(userId, classNames, max);
577            }
578    
579            /**
580             * Returns the guest or current user's groups &quot;sites&quot; associated
581             * with the group entity class names, including the Control Panel group if
582             * the user is permitted to view the Control Panel.
583             *
584             * <ul>
585             * <li>
586             * Class name &quot;User&quot; includes the user's layout set
587             * group.
588             * </li>
589             * <li>
590             * Class name &quot;Organization&quot; includes the user's
591             * immediate organization groups and inherited organization groups.
592             * </li>
593             * <li>
594             * Class name &quot;Group&quot; includes the user's immediate
595             * organization groups and site groups.
596             * </li>
597             * <li>
598             * A <code>classNames</code>
599             * value of <code>null</code> includes the user's layout set group,
600             * organization groups, inherited organization groups, and site groups.
601             * </li>
602             * </ul>
603             *
604             * @param      classNames the group entity class names (optionally
605             *             <code>null</code>). For more information see {@link
606             *             #getUserSitesGroups(String[], int)}
607             * @param      max the maximum number of groups to return
608             * @return     the user's groups &quot;sites&quot;
609             * @throws     PortalException if a portal exception occurred
610             * @throws     SystemException if a system exception occurred
611             * @deprecated As of 6.2.0, replaced by {@link #getUserSitesGroups(
612             *             String[], int)}
613             */
614            @Override
615            public List<Group> getUserPlaces(String[] classNames, int max)
616                    throws PortalException, SystemException {
617    
618                    return getUserSitesGroups(classNames, max);
619            }
620    
621            /**
622             * Returns the number of the guest or current user's groups
623             * &quot;sites&quot; associated with the group entity class names, including
624             * the Control Panel group if the user is permitted to view the Control
625             * Panel.
626             *
627             * @return     the number of user's groups &quot;sites&quot;
628             * @throws     PortalException if a portal exception occurred
629             * @throws     SystemException if a system exception occurred
630             * @deprecated As of 6.2.0, replaced by {@link #getUserSitesGroupsCount()}
631             */
632            @Override
633            public int getUserPlacesCount() throws PortalException, SystemException {
634                    return getUserSitesGroupsCount();
635            }
636    
637            /**
638             * Returns the guest or current user's layout set group, organization
639             * groups, inherited organization groups, and site groups.
640             *
641             * @return     the user's layout set group, organization groups, and
642             *             inherited organization groups, and site groups
643             * @throws     PortalException if a portal exception occurred
644             * @throws     SystemException if a system exception occurred
645             * @deprecated As of 6.2.0, replaced by {@link #getUserSitesGroups}
646             */
647            @Override
648            public List<Group> getUserSites() throws PortalException, SystemException {
649                    return getUserSitesGroups();
650            }
651    
652            @Override
653            public List<Group> getUserSitesGroups()
654                    throws PortalException, SystemException {
655    
656                    return getUserSitesGroups(null, QueryUtil.ALL_POS);
657            }
658    
659            @Override
660            public List<Group> getUserSitesGroups(
661                            long userId, String[] classNames, boolean includeControlPanel,
662                            int max)
663                    throws PortalException, SystemException {
664    
665                    User user = userPersistence.fetchByPrimaryKey(userId);
666    
667                    if (user.isDefaultUser()) {
668                            return Collections.emptyList();
669                    }
670    
671                    List<Group> userSiteGroups = new UniqueList<Group>();
672    
673                    int start = QueryUtil.ALL_POS;
674                    int end = QueryUtil.ALL_POS;
675    
676                    if (max != QueryUtil.ALL_POS) {
677                            start = 0;
678                            end = max;
679                    }
680    
681                    if ((classNames == null) ||
682                            ArrayUtil.contains(classNames, Group.class.getName())) {
683    
684                            LinkedHashMap<String, Object> groupParams =
685                                    new LinkedHashMap<String, Object>();
686    
687                            groupParams.put("active", true);
688                            groupParams.put("usersGroups", userId);
689    
690                            userSiteGroups.addAll(
691                                    groupLocalService.search(
692                                            user.getCompanyId(), null, groupParams, start, end));
693                    }
694    
695                    if ((classNames == null) ||
696                            ArrayUtil.contains(classNames, Organization.class.getName())) {
697    
698                            List<Organization> userOrgs =
699                                    organizationLocalService.getOrganizations(
700                                            userId, start, end, null);
701    
702                            for (Organization organization : userOrgs) {
703                                    if (!organization.hasPrivateLayouts() &&
704                                            !organization.hasPublicLayouts()) {
705    
706                                            userSiteGroups.remove(organization.getGroup());
707                                    }
708                                    else {
709                                            userSiteGroups.add(0, organization.getGroup());
710                                    }
711    
712                                    if (!PropsValues.ORGANIZATIONS_MEMBERSHIP_STRICT) {
713                                            for (Organization ancestorOrganization :
714                                                            organization.getAncestors()) {
715    
716                                                    if (!ancestorOrganization.hasPrivateLayouts() &&
717                                                            !ancestorOrganization.hasPublicLayouts()) {
718    
719                                                            continue;
720                                                    }
721    
722                                                    userSiteGroups.add(0, ancestorOrganization.getGroup());
723                                            }
724                                    }
725                            }
726                    }
727    
728                    if ((classNames == null) ||
729                            ArrayUtil.contains(classNames, User.class.getName())) {
730    
731                            if (PropsValues.LAYOUT_USER_PRIVATE_LAYOUTS_ENABLED ||
732                                    PropsValues.LAYOUT_USER_PUBLIC_LAYOUTS_ENABLED) {
733    
734                                    Group userGroup = user.getGroup();
735    
736                                    userSiteGroups.add(0, userGroup);
737                            }
738                    }
739    
740                    PermissionChecker permissionChecker = getPermissionChecker();
741    
742                    if (permissionChecker.getUserId() != userId) {
743                            try {
744                                    permissionChecker = PermissionCheckerFactoryUtil.create(user);
745                            }
746                            catch (Exception e) {
747                                    throw new PrincipalException(e);
748                            }
749                    }
750    
751                    if (includeControlPanel &&
752                            PortalPermissionUtil.contains(
753                                    permissionChecker, ActionKeys.VIEW_CONTROL_PANEL)) {
754    
755                            Group controlPanelGroup = groupLocalService.getGroup(
756                                    user.getCompanyId(), GroupConstants.CONTROL_PANEL);
757    
758                            userSiteGroups.add(0, controlPanelGroup);
759                    }
760    
761                    return Collections.unmodifiableList(
762                            ListUtil.subList(userSiteGroups, start, end));
763            }
764    
765            /**
766             * Returns the user's groups &quot;sites&quot; associated with the group
767             * entity class names, including the Control Panel group if the user is
768             * permitted to view the Control Panel.
769             *
770             * <ul>
771             * <li>
772             * Class name &quot;User&quot; includes the user's layout set
773             * group.
774             * </li>
775             * <li>
776             * Class name &quot;Organization&quot; includes the user's
777             * immediate organization groups and inherited organization groups.
778             * </li>
779             * <li>
780             * Class name &quot;Group&quot; includes the user's immediate
781             * organization groups and site groups.
782             * </li>
783             * <li>
784             * A <code>classNames</code>
785             * value of <code>null</code> includes the user's layout set group,
786             * organization groups, inherited organization groups, and site groups.
787             * </li>
788             * </ul>
789             *
790             * @param  userId the primary key of the user
791             * @param  classNames the group entity class names (optionally
792             *         <code>null</code>). For more information see {@link
793             *         #getUserSitesGroups(long, String[], boolean, int)}
794             * @param  max the maximum number of groups to return
795             * @return the user's groups &quot;sites&quot;
796             * @throws PortalException if a portal exception occurred
797             * @throws SystemException if a system exception occurred
798             */
799            @Override
800            public List<Group> getUserSitesGroups(
801                            long userId, String[] classNames, int max)
802                    throws PortalException, SystemException {
803    
804                    return getUserSitesGroups(userId, classNames, false, max);
805            }
806    
807            /**
808             * Returns the guest or current user's groups &quot;sites&quot; associated
809             * with the group entity class names, including the Control Panel group if
810             * the user is permitted to view the Control Panel.
811             *
812             * <ul>
813             * <li>
814             * Class name &quot;User&quot; includes the user's layout set
815             * group.
816             * </li>
817             * <li>
818             * Class name &quot;Organization&quot; includes the user's
819             * immediate organization groups and inherited organization groups.
820             * </li>
821             * <li>
822             * Class name &quot;Group&quot; includes the user's immediate
823             * organization groups and site groups.
824             * </li>
825             * <li>
826             * A <code>classNames</code>
827             * value of <code>null</code> includes the user's layout set group,
828             * organization groups, inherited organization groups, and site groups.
829             * </li>
830             * </ul>
831             *
832             * @param  classNames the group entity class names (optionally
833             *         <code>null</code>). For more information see {@link
834             *         #getUserSitesGroups(long, String[], boolean, int)}
835             * @param  max the maximum number of groups to return
836             * @return the user's groups &quot;sites&quot;
837             * @throws PortalException if a portal exception occurred
838             * @throws SystemException if a system exception occurred
839             */
840            @Override
841            public List<Group> getUserSitesGroups(String[] classNames, int max)
842                    throws PortalException, SystemException {
843    
844                    return getUserSitesGroups(getGuestOrUserId(), classNames, false, max);
845            }
846    
847            /**
848             * Returns the number of the guest or current user's groups
849             * &quot;sites&quot; associated with the group entity class names, including
850             * the Control Panel group if the user is permitted to view the Control
851             * Panel.
852             *
853             * @return the number of user's groups &quot;sites&quot;
854             * @throws PortalException if a portal exception occurred
855             * @throws SystemException if a system exception occurred
856             */
857            @Override
858            public int getUserSitesGroupsCount()
859                    throws PortalException, SystemException {
860    
861                    List<Group> userSitesGroups = getUserSitesGroups(
862                            getGuestOrUserId(), null, true, QueryUtil.ALL_POS);
863    
864                    return userSitesGroups.size();
865            }
866    
867            /**
868             * Returns <code>true</code> if the user is associated with the group,
869             * including the user's inherited organizations and user groups. System and
870             * staged groups are not included.
871             *
872             * @param  userId the primary key of the user
873             * @param  groupId the primary key of the group
874             * @return <code>true</code> if the user is associated with the group;
875             *         <code>false</code> otherwise
876             * @throws PortalException if the current user did not have permission to
877             *         view the user or group members
878             * @throws SystemException if a system exception occurred
879             */
880            @Override
881            public boolean hasUserGroup(long userId, long groupId)
882                    throws PortalException, SystemException {
883    
884                    try {
885                            UserPermissionUtil.check(
886                                    getPermissionChecker(), userId, ActionKeys.VIEW);
887                    }
888                    catch (PrincipalException pe) {
889                            GroupPermissionUtil.check(
890                                    getPermissionChecker(), groupId, ActionKeys.VIEW_MEMBERS);
891                    }
892    
893                    return groupLocalService.hasUserGroup(userId, groupId);
894            }
895    
896            /**
897             * Returns an ordered range of all the site groups and organization groups
898             * that match the name and description, optionally including the user's
899             * inherited organization groups and user groups. System and staged groups
900             * are not included.
901             *
902             * <p>
903             * Useful when paginating results. Returns a maximum of <code>end -
904             * start</code> instances. <code>start</code> and <code>end</code> are not
905             * primary keys, they are indexes in the result set. Thus, <code>0</code>
906             * refers to the first result in the set. Setting both <code>start</code>
907             * and <code>end</code> to {@link
908             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
909             * result set.
910             * </p>
911             *
912             * @param  companyId the primary key of the company
913             * @param  name the group's name (optionally <code>null</code>)
914             * @param  description the group's description (optionally
915             *         <code>null</code>)
916             * @param  params the finder params (optionally <code>null</code>). To
917             *         include the user's inherited organizations and user groups in the
918             *         search, add entries having &quot;usersGroups&quot; and
919             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
920             *         information see {@link
921             *         com.liferay.portal.service.persistence.GroupFinder}
922             * @param  start the lower bound of the range of groups to return
923             * @param  end the upper bound of the range of groups to return (not
924             *         inclusive)
925             * @return the matching groups ordered by name
926             * @throws PortalException if a portal exception occurred
927             * @throws SystemException if a system exception occurred
928             */
929            @Override
930            public List<Group> search(
931                            long companyId, String name, String description, String[] params,
932                            int start, int end)
933                    throws PortalException, SystemException {
934    
935                    if (params == null) {
936                            params = new String[0];
937                    }
938    
939                    LinkedHashMap<String, Object> paramsObj = MapUtil.toLinkedHashMap(
940                            params);
941    
942                    List<Group> groups = groupLocalService.search(
943                            companyId, name, description, paramsObj, true, start, end);
944    
945                    return filterGroups(groups);
946            }
947    
948            /**
949             * Returns the number of groups and organization groups that match the name
950             * and description, optionally including the user's inherited organizations
951             * and user groups. System and staged groups are not included.
952             *
953             * @param  companyId the primary key of the company
954             * @param  name the group's name (optionally <code>null</code>)
955             * @param  description the group's description (optionally
956             *         <code>null</code>)
957             * @param  params the finder params (optionally <code>null</code>). To
958             *         include the user's inherited organizations and user groups in the
959             *         search, add entries having &quot;usersGroups&quot; and
960             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
961             *         information see {@link
962             *         com.liferay.portal.service.persistence.GroupFinder}
963             * @return the number of matching groups
964             * @throws SystemException if a system exception occurred
965             */
966            @Override
967            public int searchCount(
968                            long companyId, String name, String description, String[] params)
969                    throws SystemException {
970    
971                    if (params == null) {
972                            params = new String[0];
973                    }
974    
975                    LinkedHashMap<String, Object> paramsObj = MapUtil.toLinkedHashMap(
976                            params);
977    
978                    return groupLocalService.searchCount(
979                            companyId, name, description, paramsObj, true);
980            }
981    
982            /**
983             * Sets the groups associated with the role, removing and adding
984             * associations as necessary.
985             *
986             * @param  roleId the primary key of the role
987             * @param  groupIds the primary keys of the groups
988             * @throws PortalException if the user did not have permission to update
989             *         update the role
990             * @throws SystemException if a system exception occurred
991             */
992            @Override
993            public void setRoleGroups(long roleId, long[] groupIds)
994                    throws PortalException, SystemException {
995    
996                    RolePermissionUtil.check(
997                            getPermissionChecker(), roleId, ActionKeys.ASSIGN_MEMBERS);
998    
999                    groupLocalService.setRoleGroups(roleId, groupIds);
1000            }
1001    
1002            /**
1003             * Removes the groups from the role.
1004             *
1005             * @param  roleId the primary key of the role
1006             * @param  groupIds the primary keys of the groups
1007             * @throws PortalException if the user did not have permission to update the
1008             *         role
1009             * @throws SystemException if a system exception occurred
1010             */
1011            @Override
1012            public void unsetRoleGroups(long roleId, long[] groupIds)
1013                    throws PortalException, SystemException {
1014    
1015                    RolePermissionUtil.check(
1016                            getPermissionChecker(), roleId, ActionKeys.ASSIGN_MEMBERS);
1017    
1018                    groupLocalService.unsetRoleGroups(roleId, groupIds);
1019            }
1020    
1021            /**
1022             * Updates the group's friendly URL.
1023             *
1024             * @param  groupId the primary key of the group
1025             * @param  friendlyURL the group's new friendlyURL (optionally
1026             *         <code>null</code>)
1027             * @return the group
1028             * @throws PortalException if the user did not have permission to update the
1029             *         group, if a group with the primary key could not be found, or if
1030             *         a valid friendly URL could not be created for the group
1031             * @throws SystemException if a system exception occurred
1032             */
1033            @Override
1034            public Group updateFriendlyURL(long groupId, String friendlyURL)
1035                    throws PortalException, SystemException {
1036    
1037                    GroupPermissionUtil.check(
1038                            getPermissionChecker(), groupId, ActionKeys.UPDATE);
1039    
1040                    return groupLocalService.updateFriendlyURL(groupId, friendlyURL);
1041            }
1042    
1043            /**
1044             * Updates the group.
1045             *
1046             * @param  groupId the primary key of the group
1047             * @param  parentGroupId the primary key of the parent group
1048             * @param  name the group's new name
1049             * @param  description the group's new description (optionally
1050             *         <code>null</code>)
1051             * @param  type the group's new type. For more information see {@link
1052             *         com.liferay.portal.model.GroupConstants}
1053             * @param  friendlyURL the group's new friendlyURL (optionally
1054             *         <code>null</code>)
1055             * @param  active whether the group is active
1056             * @param  serviceContext the service context to be applied (optionally
1057             *         <code>null</code>). Can set the asset category IDs and asset tag
1058             *         names for the group.
1059             * @return the group
1060             * @throws PortalException if the user did not have permission to update the
1061             *         group, if a group with the primary key could not be found, if the
1062             *         friendly URL was invalid or could one not be created
1063             * @throws SystemException if a system exception occurred
1064             */
1065            @Override
1066            public Group updateGroup(
1067                            long groupId, long parentGroupId, String name, String description,
1068                            int type, boolean manualMembership, int membershipRestriction,
1069                            String friendlyURL, boolean active, ServiceContext serviceContext)
1070                    throws PortalException, SystemException {
1071    
1072                    Group group = groupPersistence.findByPrimaryKey(groupId);
1073    
1074                    GroupPermissionUtil.check(
1075                            getPermissionChecker(), group, ActionKeys.UPDATE);
1076    
1077                    if (group.getParentGroupId() != parentGroupId) {
1078                            if (parentGroupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
1079                                    PortalPermissionUtil.check(
1080                                            getPermissionChecker(), ActionKeys.ADD_COMMUNITY);
1081                            }
1082                            else {
1083                                    GroupPermissionUtil.check(
1084                                            getPermissionChecker(), parentGroupId,
1085                                            ActionKeys.ADD_COMMUNITY);
1086                            }
1087                    }
1088    
1089                    if (group.isSite()) {
1090                            Group oldGroup = group;
1091    
1092                            List<AssetCategory> oldAssetCategories =
1093                                    assetCategoryLocalService.getCategories(
1094                                            Group.class.getName(), groupId);
1095    
1096                            List<AssetTag> oldAssetTags = assetTagLocalService.getTags(
1097                                    Group.class.getName(), groupId);
1098    
1099                            ExpandoBridge oldExpandoBridge = oldGroup.getExpandoBridge();
1100    
1101                            Map<String, Serializable> oldExpandoAttributes =
1102                                    oldExpandoBridge.getAttributes();
1103    
1104                            group = groupLocalService.updateGroup(
1105                                    groupId, parentGroupId, name, description, type,
1106                                    manualMembership, membershipRestriction, friendlyURL, active,
1107                                    serviceContext);
1108    
1109                            SiteMembershipPolicyUtil.verifyPolicy(
1110                                    group, oldGroup, oldAssetCategories, oldAssetTags,
1111                                    oldExpandoAttributes, null);
1112    
1113                            return group;
1114                    }
1115                    else {
1116                            return groupLocalService.updateGroup(
1117                                    groupId, parentGroupId, name, description, type,
1118                                    manualMembership, membershipRestriction, friendlyURL, active,
1119                                    serviceContext);
1120                    }
1121            }
1122    
1123            /**
1124             * Updates the group's type settings.
1125             *
1126             * @param  groupId the primary key of the group
1127             * @param  typeSettings the group's new type settings (optionally
1128             *         <code>null</code>)
1129             * @return the group
1130             * @throws PortalException if the user did not have permission to update the
1131             *         group or if a group with the primary key could not be found
1132             * @throws SystemException if a system exception occurred
1133             */
1134            @Override
1135            public Group updateGroup(long groupId, String typeSettings)
1136                    throws PortalException, SystemException {
1137    
1138                    GroupPermissionUtil.check(
1139                            getPermissionChecker(), groupId, ActionKeys.UPDATE);
1140    
1141                    Group group = groupPersistence.findByPrimaryKey(groupId);
1142    
1143                    if (group.isSite()) {
1144                            Group oldGroup = group;
1145    
1146                            UnicodeProperties oldTypeSettingsProperties =
1147                                    oldGroup.getTypeSettingsProperties();
1148    
1149                            group = groupLocalService.updateGroup(groupId, typeSettings);
1150    
1151                            SiteMembershipPolicyUtil.verifyPolicy(
1152                                    group, oldGroup, null, null, null, oldTypeSettingsProperties);
1153    
1154                            return group;
1155                    }
1156                    else {
1157                            return groupLocalService.updateGroup(groupId, typeSettings);
1158                    }
1159            }
1160    
1161            @Override
1162            public void updateStagedPortlets(
1163                            long groupId, Map<String, String> stagedPortletIds)
1164                    throws PortalException, SystemException {
1165    
1166                    GroupPermissionUtil.check(
1167                            getPermissionChecker(), groupId, ActionKeys.UPDATE);
1168    
1169                    Group group = groupPersistence.findByPrimaryKey(groupId);
1170    
1171                    UnicodeProperties typeSettingsProperties =
1172                            group.getTypeSettingsProperties();
1173    
1174                    for (String stagedPortletId : stagedPortletIds.keySet()) {
1175                            typeSettingsProperties.setProperty(
1176                                    StagingUtil.getStagedPortletId(stagedPortletId),
1177                                    stagedPortletIds.get(stagedPortletId));
1178                    }
1179    
1180                    groupLocalService.updateGroup(group);
1181            }
1182    
1183            protected List<Group> filterGroups(List<Group> groups)
1184                    throws PortalException, SystemException {
1185    
1186                    List<Group> filteredGroups = new ArrayList<Group>();
1187    
1188                    for (Group group : groups) {
1189                            if (GroupPermissionUtil.contains(
1190                                            getPermissionChecker(), group.getGroupId(),
1191                                            ActionKeys.VIEW)) {
1192    
1193                                    filteredGroups.add(group);
1194                            }
1195                    }
1196    
1197                    return filteredGroups;
1198            }
1199    
1200    }