1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.service.impl;
16  
17  import com.liferay.portal.DuplicateGroupException;
18  import com.liferay.portal.GroupFriendlyURLException;
19  import com.liferay.portal.GroupNameException;
20  import com.liferay.portal.NoSuchGroupException;
21  import com.liferay.portal.NoSuchLayoutSetException;
22  import com.liferay.portal.RequiredGroupException;
23  import com.liferay.portal.kernel.annotation.Propagation;
24  import com.liferay.portal.kernel.annotation.Transactional;
25  import com.liferay.portal.kernel.dao.orm.QueryUtil;
26  import com.liferay.portal.kernel.exception.PortalException;
27  import com.liferay.portal.kernel.exception.SystemException;
28  import com.liferay.portal.kernel.log.Log;
29  import com.liferay.portal.kernel.log.LogFactoryUtil;
30  import com.liferay.portal.kernel.messaging.DestinationNames;
31  import com.liferay.portal.kernel.scheduler.SchedulerEngineUtil;
32  import com.liferay.portal.kernel.scheduler.messaging.SchedulerRequest;
33  import com.liferay.portal.kernel.util.GetterUtil;
34  import com.liferay.portal.kernel.util.OrderByComparator;
35  import com.liferay.portal.kernel.util.PropsKeys;
36  import com.liferay.portal.kernel.util.StringPool;
37  import com.liferay.portal.kernel.util.StringUtil;
38  import com.liferay.portal.kernel.util.UnicodeProperties;
39  import com.liferay.portal.kernel.util.Validator;
40  import com.liferay.portal.lar.PortletDataHandlerKeys;
41  import com.liferay.portal.model.Company;
42  import com.liferay.portal.model.Group;
43  import com.liferay.portal.model.GroupConstants;
44  import com.liferay.portal.model.Layout;
45  import com.liferay.portal.model.LayoutConstants;
46  import com.liferay.portal.model.LayoutPrototype;
47  import com.liferay.portal.model.LayoutSet;
48  import com.liferay.portal.model.LayoutSetPrototype;
49  import com.liferay.portal.model.LayoutTypePortlet;
50  import com.liferay.portal.model.Organization;
51  import com.liferay.portal.model.Resource;
52  import com.liferay.portal.model.ResourceConstants;
53  import com.liferay.portal.model.Role;
54  import com.liferay.portal.model.RoleConstants;
55  import com.liferay.portal.model.User;
56  import com.liferay.portal.model.UserGroup;
57  import com.liferay.portal.model.impl.LayoutImpl;
58  import com.liferay.portal.security.permission.PermissionCacheUtil;
59  import com.liferay.portal.service.ServiceContext;
60  import com.liferay.portal.service.base.GroupLocalServiceBaseImpl;
61  import com.liferay.portal.util.FriendlyURLNormalizer;
62  import com.liferay.portal.util.PortalUtil;
63  import com.liferay.portal.util.PropsUtil;
64  import com.liferay.portal.util.PropsValues;
65  import com.liferay.portal.util.comparator.GroupNameComparator;
66  import com.liferay.portlet.communities.util.StagingUtil;
67  import com.liferay.util.UniqueList;
68  
69  import java.io.File;
70  
71  import java.util.ArrayList;
72  import java.util.HashMap;
73  import java.util.Iterator;
74  import java.util.LinkedHashMap;
75  import java.util.List;
76  import java.util.Map;
77  
78  /**
79   * <a href="GroupLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
80   *
81   * @author Brian Wing Shun Chan
82   * @author Alexander Chow
83   * @author Bruno Farache
84   * @author Wesley Gong
85   */
86  public class GroupLocalServiceImpl extends GroupLocalServiceBaseImpl {
87  
88      public GroupLocalServiceImpl() {
89          initImportLARFile();
90      }
91  
92      public Group addGroup(
93              long userId, String className, long classPK, String name,
94              String description, int type, String friendlyURL, boolean active,
95              ServiceContext serviceContext)
96          throws PortalException, SystemException {
97  
98          return addGroup(
99              userId, className, classPK, GroupConstants.DEFAULT_LIVE_GROUP_ID,
100             name, description, type, friendlyURL, active, serviceContext);
101     }
102 
103     public Group addGroup(
104             long userId, String className, long classPK, long liveGroupId,
105             String name, String description, int type, String friendlyURL,
106             boolean active, ServiceContext serviceContext)
107         throws PortalException, SystemException {
108 
109         // Group
110 
111         User user = userPersistence.findByPrimaryKey(userId);
112         className = GetterUtil.getString(className);
113         long classNameId = PortalUtil.getClassNameId(className);
114 
115         String friendlyName = name;
116 
117         if (className.equals(Organization.class.getName())) {
118             Organization organization =
119                 organizationPersistence.findByPrimaryKey(classPK);
120 
121             friendlyName = organization.getName();
122         }
123 
124         long groupId = 0;
125 
126         while (true) {
127             groupId = counterLocalService.increment();
128 
129             User userScreenName = userPersistence.fetchByC_SN(
130                 user.getCompanyId(), String.valueOf(groupId));
131 
132             if (userScreenName == null) {
133                 break;
134             }
135         }
136 
137         long groupClassNameId = PortalUtil.getClassNameId(Group.class);
138 
139         if ((classNameId <= 0) || className.equals(Group.class.getName())) {
140             validateName(groupId, user.getCompanyId(), name);
141 
142             classNameId = groupClassNameId;
143             classPK = groupId;
144         }
145         else {
146             name = String.valueOf(classPK);
147         }
148 
149         long parentGroupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
150 
151         if (className.equals(Layout.class.getName())) {
152             Layout layout = layoutLocalService.getLayout(classPK);
153 
154             parentGroupId = layout.getGroupId();
155         }
156 
157         friendlyURL = getFriendlyURL(
158             user.getCompanyId(), groupId, classNameId, classPK, friendlyName,
159             friendlyURL);
160 
161         validateFriendlyURL(
162             user.getCompanyId(), groupId, classNameId, classPK, friendlyURL);
163 
164         Group group = groupPersistence.create(groupId);
165 
166         group.setCompanyId(user.getCompanyId());
167         group.setCreatorUserId(userId);
168         group.setClassNameId(classNameId);
169         group.setClassPK(classPK);
170         group.setParentGroupId(parentGroupId);
171         group.setLiveGroupId(liveGroupId);
172         group.setName(name);
173         group.setDescription(description);
174         group.setType(type);
175         group.setFriendlyURL(friendlyURL);
176         group.setActive(active);
177 
178         groupPersistence.update(group, false);
179 
180         // Layout sets
181 
182         layoutSetLocalService.addLayoutSet(groupId, true);
183 
184         layoutSetLocalService.addLayoutSet(groupId, false);
185 
186         if ((classNameId == groupClassNameId) && !user.isDefaultUser()) {
187 
188             // Resources
189 
190             resourceLocalService.addResources(
191                 group.getCompanyId(), 0, 0, Group.class.getName(),
192                 group.getGroupId(), false, false, false);
193 
194             // Community roles
195 
196             Role role = roleLocalService.getRole(
197                 group.getCompanyId(), RoleConstants.COMMUNITY_OWNER);
198 
199             userGroupRoleLocalService.addUserGroupRoles(
200                 userId, groupId, new long[] {role.getRoleId()});
201 
202             // User
203 
204             userLocalService.addGroupUsers(
205                 group.getGroupId(), new long[] {userId});
206 
207             // Asset
208 
209             if (serviceContext != null) {
210                 updateAsset(
211                     userId, group, serviceContext.getAssetCategoryIds(),
212                     serviceContext.getAssetTagNames());
213             }
214         }
215         else if (className.equals(Organization.class.getName()) &&
216                  !user.isDefaultUser()) {
217 
218             // Resources
219 
220             resourceLocalService.addResources(
221                 group.getCompanyId(), 0, 0, Group.class.getName(),
222                 group.getGroupId(), false, false, false);
223         }
224 
225         return group;
226     }
227 
228     public void addRoleGroups(long roleId, long[] groupIds)
229         throws SystemException {
230 
231         rolePersistence.addGroups(roleId, groupIds);
232 
233         PermissionCacheUtil.clearCache();
234     }
235 
236     public void addUserGroups(long userId, long[] groupIds)
237         throws SystemException {
238 
239         userPersistence.addGroups(userId, groupIds);
240 
241         PermissionCacheUtil.clearCache();
242     }
243 
244     @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
245     public void checkCompanyGroup(long companyId)
246         throws PortalException, SystemException {
247 
248         long classNameId = PortalUtil.getClassNameId(Company.class);
249 
250         int count = groupPersistence.countByC_C_C(
251             companyId, classNameId, companyId);
252 
253         if (count == 0) {
254             long defaultUserId = userLocalService.getDefaultUserId(companyId);
255 
256             groupLocalService.addGroup(
257                 defaultUserId, Company.class.getName(), companyId, null, null,
258                 0, null, true, null);
259         }
260     }
261 
262     @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
263     public void checkSystemGroups(long companyId)
264         throws PortalException, SystemException {
265 
266         for (Group group : groupFinder.findBySystem(companyId)) {
267             _systemGroupsMap.put(companyId + group.getName(), group);
268         }
269 
270         long defaultUserId = userLocalService.getDefaultUserId(companyId);
271 
272         String[] systemGroups = PortalUtil.getSystemGroups();
273 
274         for (String name : systemGroups) {
275             Group group = _systemGroupsMap.get(companyId + name);
276 
277             try {
278                 if (group == null) {
279                     group = groupPersistence.findByC_N(companyId, name);
280                 }
281             }
282             catch (NoSuchGroupException nsge) {
283                 int type = GroupConstants.TYPE_COMMUNITY_OPEN;
284                 String friendlyURL = null;
285 
286                 if (name.equals(GroupConstants.CONTROL_PANEL)) {
287                     type = GroupConstants.TYPE_COMMUNITY_PRIVATE;
288                     friendlyURL = GroupConstants.CONTROL_PANEL_FRIENDLY_URL;
289                 }
290                 else if (name.equals(GroupConstants.GUEST)) {
291                     friendlyURL = "/guest";
292                 }
293 
294                 group = groupLocalService.addGroup(
295                     defaultUserId, null, 0, name, null, type, friendlyURL,
296                     true, null);
297             }
298 
299             if (group.isControlPanel()) {
300                 LayoutSet layoutSet = layoutSetLocalService.getLayoutSet(
301                     group.getGroupId(), true);
302 
303                 if (layoutSet.getPageCount() == 0) {
304                     addControlPanelLayouts(group);
305                 }
306             }
307 
308             if (group.getName().equals(GroupConstants.GUEST)) {
309                 LayoutSet layoutSet = layoutSetLocalService.getLayoutSet(
310                     group.getGroupId(), false);
311 
312                 if (layoutSet.getPageCount() == 0) {
313                     addDefaultGuestPublicLayouts(group);
314                 }
315             }
316 
317             _systemGroupsMap.put(companyId + name, group);
318         }
319     }
320 
321     public void deleteGroup(long groupId)
322         throws PortalException, SystemException {
323 
324         Group group = groupPersistence.findByPrimaryKey(groupId);
325 
326         if (PortalUtil.isSystemGroup(group.getName())) {
327             throw new RequiredGroupException(String.valueOf(groupId));
328         }
329 
330         // Layout sets
331 
332         try {
333             layoutSetLocalService.deleteLayoutSet(groupId, true);
334         }
335         catch (NoSuchLayoutSetException nslse) {
336         }
337 
338         try {
339             layoutSetLocalService.deleteLayoutSet(groupId, false);
340         }
341         catch (NoSuchLayoutSetException nslse) {
342         }
343 
344         // Group roles
345 
346         userGroupRoleLocalService.deleteUserGroupRolesByGroupId(groupId);
347 
348         // User group roles
349 
350         userGroupGroupRoleLocalService.deleteUserGroupGroupRolesByGroupId(
351             groupId);
352 
353         // Membership requests
354 
355         membershipRequestLocalService.deleteMembershipRequests(
356             group.getGroupId());
357 
358         /// Teams
359 
360         teamLocalService.deleteTeams(group.getGroupId());
361 
362         // Staging
363 
364         unscheduleStaging(group);
365 
366         if (group.hasStagingGroup()) {
367             deleteGroup(group.getStagingGroup().getGroupId());
368         }
369 
370         // Asset
371 
372         if (group.isCommunity()) {
373             assetEntryLocalService.deleteEntry(Group.class.getName(), groupId);
374         }
375 
376         // Blogs
377 
378         blogsEntryLocalService.deleteEntries(groupId);
379         blogsStatsUserLocalService.deleteStatsUserByGroupId(groupId);
380 
381         // Bookmarks
382 
383         bookmarksFolderLocalService.deleteFolders(groupId);
384 
385         // Calendar
386 
387         calEventLocalService.deleteEvents(groupId);
388 
389         // Document library
390 
391         dlFolderLocalService.deleteFolders(groupId);
392 
393         // Image gallery
394 
395         igFolderLocalService.deleteFolders(groupId);
396 
397         // Journal
398 
399         journalArticleLocalService.deleteArticles(groupId);
400         journalTemplateLocalService.deleteTemplates(groupId);
401         journalStructureLocalService.deleteStructures(groupId);
402 
403         // Message boards
404 
405         mbBanLocalService.deleteBansByGroupId(groupId);
406         mbCategoryLocalService.deleteCategories(groupId);
407         mbStatsUserLocalService.deleteStatsUsersByGroupId(groupId);
408 
409         // Polls
410 
411         pollsQuestionLocalService.deleteQuestions(groupId);
412 
413         // Shopping
414 
415         shoppingCartLocalService.deleteGroupCarts(groupId);
416         shoppingCategoryLocalService.deleteCategories(groupId);
417         shoppingCouponLocalService.deleteCoupons(groupId);
418         shoppingOrderLocalService.deleteOrders(groupId);
419 
420         // Software catalog
421 
422         scFrameworkVersionLocalService.deleteFrameworkVersions(groupId);
423         scProductEntryLocalService.deleteProductEntries(groupId);
424 
425         // Wiki
426 
427         wikiNodeLocalService.deleteNodes(groupId);
428 
429         // Resources
430 
431         Iterator<Resource> itr = resourceFinder.findByC_P(
432             group.getCompanyId(), String.valueOf(groupId)).iterator();
433 
434         while (itr.hasNext()) {
435             Resource resource = itr.next();
436 
437             resourceLocalService.deleteResource(resource);
438         }
439 
440         if (!group.isStagingGroup() &&
441             (group.isCommunity() || group.isOrganization())) {
442 
443             resourceLocalService.deleteResource(
444                 group.getCompanyId(), Group.class.getName(),
445                 ResourceConstants.SCOPE_INDIVIDUAL, group.getGroupId());
446         }
447 
448         // Group
449 
450         groupPersistence.remove(group);
451 
452         // Permission cache
453 
454         PermissionCacheUtil.clearCache();
455     }
456 
457     public Group getCompanyGroup(long companyId)
458         throws PortalException, SystemException {
459 
460         long classNameId = PortalUtil.getClassNameId(Company.class);
461 
462         return groupPersistence.findByC_C_C(companyId, classNameId, companyId);
463     }
464 
465     public List<Group> getCompanyGroups(long companyId, int start, int end)
466         throws SystemException {
467 
468         return groupPersistence.findByCompanyId(companyId, start, end);
469     }
470 
471     public int getCompanyGroupsCount(long companyId) throws SystemException {
472         return groupPersistence.countByCompanyId(companyId);
473     }
474 
475     public Group getFriendlyURLGroup(long companyId, String friendlyURL)
476         throws PortalException, SystemException {
477 
478         if (Validator.isNull(friendlyURL)) {
479             throw new NoSuchGroupException();
480         }
481 
482         friendlyURL = getFriendlyURL(friendlyURL);
483 
484         return groupPersistence.findByC_F(companyId, friendlyURL);
485     }
486 
487     public Group getGroup(long groupId)
488         throws PortalException, SystemException {
489 
490         return groupPersistence.findByPrimaryKey(groupId);
491     }
492 
493     public Group getGroup(long companyId, String name)
494         throws PortalException, SystemException {
495 
496         Group group = _systemGroupsMap.get(companyId + name);
497 
498         if (group != null) {
499             return group;
500         }
501 
502         return groupPersistence.findByC_N(companyId, name);
503     }
504 
505     public List<Group> getGroups(long[] groupIds)
506         throws PortalException, SystemException {
507 
508         List<Group> groups = new ArrayList<Group>(groupIds.length);
509 
510         for (long groupId : groupIds) {
511             Group group = getGroup(groupId);
512 
513             groups.add(group);
514         }
515 
516         return groups;
517     }
518 
519     public Group getLayoutGroup(long companyId, long plid)
520         throws PortalException, SystemException {
521 
522         long classNameId = PortalUtil.getClassNameId(Layout.class);
523 
524         return groupPersistence.findByC_C_C(companyId, classNameId, plid);
525     }
526 
527     public Group getLayoutPrototypeGroup(long companyId, long layoutPrototypeId)
528         throws PortalException, SystemException {
529 
530         long classNameId = PortalUtil.getClassNameId(LayoutPrototype.class);
531 
532         return groupPersistence.findByC_C_C(
533             companyId, classNameId, layoutPrototypeId);
534     }
535 
536     public Group getLayoutSetPrototypeGroup(
537             long companyId, long layoutSetPrototypeId)
538         throws PortalException, SystemException {
539 
540         long classNameId = PortalUtil.getClassNameId(LayoutSetPrototype.class);
541 
542         return groupPersistence.findByC_C_C(
543             companyId, classNameId, layoutSetPrototypeId);
544     }
545 
546     public List<Group> getNoLayoutsGroups(
547             String className, boolean privateLayout, int start, int end)
548         throws SystemException {
549 
550         long classNameId = PortalUtil.getClassNameId(className);
551 
552         return groupFinder.findByNoLayouts(
553             classNameId, privateLayout, start, end);
554     }
555 
556     public List<Group> getNullFriendlyURLGroups() throws SystemException {
557         return groupFinder.findByNullFriendlyURL();
558     }
559 
560     public Group getOrganizationGroup(long companyId, long organizationId)
561         throws PortalException, SystemException {
562 
563         long classNameId = PortalUtil.getClassNameId(Organization.class);
564 
565         return groupPersistence.findByC_C_C(
566             companyId, classNameId, organizationId);
567     }
568 
569     public List<Group> getOrganizationsGroups(
570         List<Organization> organizations) {
571 
572         List<Group> organizationGroups = new ArrayList<Group>();
573 
574         for (int i = 0; i < organizations.size(); i++) {
575             Organization organization = organizations.get(i);
576 
577             Group group = organization.getGroup();
578 
579             organizationGroups.add(group);
580         }
581 
582         return organizationGroups;
583     }
584 
585     public List<Group> getRoleGroups(long roleId) throws SystemException {
586         return rolePersistence.getGroups(roleId);
587     }
588 
589     public Group getStagingGroup(long liveGroupId)
590         throws PortalException, SystemException {
591 
592         return groupPersistence.findByLiveGroupId(liveGroupId);
593     }
594 
595     public Group getUserGroup(long companyId, long userId)
596         throws PortalException, SystemException {
597 
598         long classNameId = PortalUtil.getClassNameId(User.class);
599 
600         return groupPersistence.findByC_C_C(companyId, classNameId, userId);
601     }
602 
603     public Group getUserGroupGroup(long companyId, long userGroupId)
604         throws PortalException, SystemException {
605 
606         long classNameId = PortalUtil.getClassNameId(UserGroup.class);
607 
608         return groupPersistence.findByC_C_C(
609             companyId, classNameId, userGroupId);
610     }
611 
612     public List<Group> getUserGroups(long userId)
613         throws PortalException, SystemException {
614 
615         return getUserGroups(userId, false);
616     }
617 
618     public List<Group> getUserGroups(long userId, boolean inherit)
619         throws PortalException, SystemException {
620 
621         return getUserGroups(
622             userId, inherit, QueryUtil.ALL_POS, QueryUtil.ALL_POS);
623     }
624 
625     public List<Group> getUserGroups(long userId, int start, int end)
626         throws PortalException, SystemException {
627 
628         return getUserGroups(userId, false, start, end);
629     }
630 
631     public List<Group> getUserGroups(
632             long userId, boolean inherit, int start, int end)
633         throws PortalException, SystemException {
634 
635         if (inherit) {
636             User user = userPersistence.findByPrimaryKey(userId);
637 
638             LinkedHashMap<String, Object> groupParams =
639                 new LinkedHashMap<String, Object>();
640 
641             groupParams.put("usersGroups", new Long(userId));
642 
643             return search(
644                 user.getCompanyId(), null, null, groupParams, start, end);
645         }
646         else {
647             return userPersistence.getGroups(userId);
648         }
649     }
650 
651     public List<Group> getUserGroupsGroups(List<UserGroup> userGroups)
652         throws PortalException, SystemException {
653 
654         List<Group> userGroupGroups = new ArrayList<Group>();
655 
656         for (int i = 0; i < userGroups.size(); i++) {
657             UserGroup userGroup = userGroups.get(i);
658 
659             Group group = userGroup.getGroup();
660 
661             userGroupGroups.add(group);
662         }
663 
664         return userGroupGroups;
665     }
666 
667     public List<Group> getUserOrganizationsGroups(
668             long userId, int start, int end)
669         throws PortalException, SystemException {
670 
671         List<Group> userOrgsGroups = new UniqueList<Group>();
672 
673         List<Organization> userOrgs =
674             organizationLocalService.getUserOrganizations(
675                 userId, true, start, end);
676 
677         for (Organization organization : userOrgs) {
678             userOrgsGroups.add(0, organization.getGroup());
679 
680             if (!PropsValues.ORGANIZATIONS_MEMBERSHIP_STRICT) {
681                 for (Organization ancestorOrganization :
682                         organization.getAncestors()) {
683 
684                     userOrgsGroups.add(0, ancestorOrganization.getGroup());
685                 }
686             }
687         }
688 
689         return userOrgsGroups;
690     }
691 
692     public boolean hasRoleGroup(long roleId, long groupId)
693         throws SystemException {
694 
695         return rolePersistence.containsGroup(roleId, groupId);
696     }
697 
698     public boolean hasStagingGroup(long liveGroupId) throws SystemException {
699         if (groupPersistence.fetchByLiveGroupId(liveGroupId) != null) {
700             return true;
701         }
702         else {
703             return false;
704         }
705     }
706 
707     public boolean hasUserGroup(long userId, long groupId)
708         throws SystemException {
709 
710         if (groupFinder.countByG_U(groupId, userId) > 0) {
711             return true;
712         }
713         else {
714             return false;
715         }
716     }
717 
718     public List<Group> search(
719             long companyId, String name, String description,
720             LinkedHashMap<String, Object> params, int start, int end)
721         throws SystemException {
722 
723         return search(companyId, name, description, params, start, end, null);
724     }
725 
726     public List<Group> search(
727             long companyId, String name, String description,
728             LinkedHashMap<String, Object> params, int start, int end,
729             OrderByComparator obc)
730         throws SystemException {
731 
732         if (obc == null) {
733             obc = new GroupNameComparator(true);
734         }
735 
736         return groupFinder.findByC_N_D(
737             companyId, name, description, params, start, end, obc);
738     }
739 
740     public int searchCount(
741             long companyId, String name, String description,
742             LinkedHashMap<String, Object> params)
743         throws SystemException {
744 
745         return groupFinder.countByC_N_D(companyId, name, description, params);
746     }
747 
748     public void setRoleGroups(long roleId, long[] groupIds)
749         throws SystemException {
750 
751         rolePersistence.setGroups(roleId, groupIds);
752 
753         PermissionCacheUtil.clearCache();
754     }
755 
756     public void unsetRoleGroups(long roleId, long[] groupIds)
757         throws SystemException {
758 
759         rolePersistence.removeGroups(roleId, groupIds);
760 
761         PermissionCacheUtil.clearCache();
762     }
763 
764     public void unsetUserGroups(long userId, long[] groupIds)
765         throws SystemException {
766 
767         userGroupRoleLocalService.deleteUserGroupRoles(userId, groupIds);
768 
769         userPersistence.removeGroups(userId, groupIds);
770 
771         PermissionCacheUtil.clearCache();
772     }
773 
774     public void updateAsset(
775             long userId, Group group, long[] assetCategoryIds,
776             String[] assetTagNames)
777         throws PortalException, SystemException {
778 
779         User user = userPersistence.findByPrimaryKey(userId);
780 
781         Company company = companyPersistence.findByPrimaryKey(
782             user.getCompanyId());
783 
784         Group companyGroup = company.getGroup();
785 
786         assetEntryLocalService.updateEntry(
787             userId, companyGroup.getGroupId(), Group.class.getName(),
788             group.getGroupId(), assetCategoryIds, assetTagNames, false, null,
789             null, null, null, null, group.getDescriptiveName(),
790             group.getDescription(), null, null, 0, 0, null, false);
791     }
792 
793     public Group updateFriendlyURL(long groupId, String friendlyURL)
794         throws PortalException, SystemException {
795 
796         Group group = groupPersistence.findByPrimaryKey(groupId);
797 
798         if (group.isUser()) {
799             User user = userPersistence.findByPrimaryKey(group.getClassPK());
800 
801             friendlyURL = StringPool.SLASH + user.getScreenName();
802 
803             if (group.getFriendlyURL().equals(friendlyURL)) {
804                 return group;
805             }
806         }
807 
808         friendlyURL = getFriendlyURL(
809             group.getCompanyId(), groupId, group.getClassNameId(),
810             group.getClassPK(), StringPool.BLANK, friendlyURL);
811 
812         validateFriendlyURL(
813             group.getCompanyId(), group.getGroupId(), group.getClassNameId(),
814             group.getClassPK(), friendlyURL);
815 
816         group.setFriendlyURL(friendlyURL);
817 
818         groupPersistence.update(group, false);
819 
820         return group;
821     }
822 
823     public Group updateGroup(
824             long groupId, String name, String description, int type,
825             String friendlyURL, boolean active, ServiceContext serviceContext)
826         throws PortalException, SystemException {
827 
828         Group group = groupPersistence.findByPrimaryKey(groupId);
829 
830         String className = group.getClassName();
831         long classNameId = group.getClassNameId();
832         long classPK = group.getClassPK();
833         friendlyURL = getFriendlyURL(
834             group.getCompanyId(), groupId, classNameId, classPK,
835             StringPool.BLANK, friendlyURL);
836 
837         if ((classNameId <= 0) || className.equals(Group.class.getName())) {
838             validateName(group.getGroupId(), group.getCompanyId(), name);
839         }
840         else {
841             name = String.valueOf(classPK);
842         }
843 
844         if (PortalUtil.isSystemGroup(group.getName()) &&
845             !group.getName().equals(name)) {
846 
847             throw new RequiredGroupException();
848         }
849 
850         validateFriendlyURL(
851             group.getCompanyId(), group.getGroupId(), group.getClassNameId(),
852             group.getClassPK(), friendlyURL);
853 
854         group.setName(name);
855         group.setDescription(description);
856         group.setType(type);
857         group.setFriendlyURL(friendlyURL);
858         group.setActive(active);
859 
860         groupPersistence.update(group, false);
861 
862         // Asset
863 
864         if ((serviceContext != null) && group.isCommunity()) {
865             updateAsset(
866                 group.getCreatorUserId(), group,
867                 serviceContext.getAssetCategoryIds(),
868                 serviceContext.getAssetTagNames());
869         }
870 
871         return group;
872     }
873 
874     public Group updateGroup(long groupId, String typeSettings)
875         throws PortalException, SystemException {
876 
877         Group group = groupPersistence.findByPrimaryKey(groupId);
878 
879         group.setTypeSettings(typeSettings);
880 
881         groupPersistence.update(group, false);
882 
883         return group;
884     }
885 
886     public Group updateWorkflow(
887             long groupId, boolean workflowEnabled, int workflowStages,
888             String workflowRoleNames)
889         throws PortalException, SystemException {
890 
891         Group group = groupPersistence.findByPrimaryKey(groupId);
892 
893         UnicodeProperties props = group.getTypeSettingsProperties();
894 
895         props.setProperty("workflowEnabled", String.valueOf(workflowEnabled));
896 
897         if (workflowEnabled) {
898             if (workflowStages < PropsValues.TASKS_DEFAULT_STAGES) {
899                 workflowStages = PropsValues.TASKS_DEFAULT_STAGES;
900             }
901 
902             if (Validator.isNull(workflowRoleNames)) {
903                 workflowRoleNames = PropsValues.TASKS_DEFAULT_ROLE_NAMES;
904             }
905 
906             props.setProperty("workflowStages", String.valueOf(workflowStages));
907             props.setProperty("workflowRoleNames", workflowRoleNames);
908         }
909 
910         group.setTypeSettings(group.getTypeSettings());
911 
912         groupPersistence.update(group, false);
913 
914         if (!workflowEnabled) {
915             tasksProposalLocalService.deleteProposals(groupId);
916         }
917 
918         return group;
919     }
920 
921     protected void addControlPanelLayouts(Group group)
922         throws PortalException, SystemException {
923 
924         long defaultUserId = userLocalService.getDefaultUserId(
925             group.getCompanyId());
926 
927         String friendlyURL = getFriendlyURL(
928             PropsValues.CONTROL_PANEL_LAYOUT_FRIENDLY_URL);
929 
930         ServiceContext serviceContext = new ServiceContext();
931 
932         layoutLocalService.addLayout(
933             defaultUserId, group.getGroupId(), true,
934             LayoutConstants.DEFAULT_PARENT_LAYOUT_ID,
935             PropsValues.CONTROL_PANEL_LAYOUT_NAME, StringPool.BLANK,
936             StringPool.BLANK, LayoutConstants.TYPE_CONTROL_PANEL, false,
937             friendlyURL, serviceContext);
938     }
939 
940     protected void addDefaultGuestPublicLayoutByProperties(Group group)
941         throws PortalException, SystemException {
942 
943         long defaultUserId = userLocalService.getDefaultUserId(
944             group.getCompanyId());
945         String friendlyURL = getFriendlyURL(
946             PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_FRIENDLY_URL);
947 
948         ServiceContext serviceContext = new ServiceContext();
949 
950         Layout layout = layoutLocalService.addLayout(
951             defaultUserId, group.getGroupId(), false,
952             LayoutConstants.DEFAULT_PARENT_LAYOUT_ID,
953             PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_NAME, StringPool.BLANK,
954             StringPool.BLANK, LayoutConstants.TYPE_PORTLET, false, friendlyURL,
955             serviceContext);
956 
957         LayoutTypePortlet layoutTypePortlet =
958             (LayoutTypePortlet)layout.getLayoutType();
959 
960         layoutTypePortlet.setLayoutTemplateId(
961             0, PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_TEMPLATE_ID, false);
962 
963         for (int i = 0; i < 10; i++) {
964             String columnId = "column-" + i;
965             String portletIds = PropsUtil.get(
966                 PropsKeys.DEFAULT_GUEST_PUBLIC_LAYOUT_COLUMN + i);
967 
968             layoutTypePortlet.addPortletIds(
969                 0, StringUtil.split(portletIds), columnId, false);
970         }
971 
972         layoutLocalService.updateLayout(
973             layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
974             layout.getTypeSettings());
975 
976         boolean updateLayoutSet = false;
977 
978         LayoutSet layoutSet = layout.getLayoutSet();
979 
980         if (Validator.isNotNull(
981                 PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_THEME_ID)) {
982 
983             layoutSet.setThemeId(
984                 PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_THEME_ID);
985 
986             updateLayoutSet = true;
987         }
988 
989         if (Validator.isNotNull(
990                 PropsValues.
991                     DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_COLOR_SCHEME_ID)) {
992 
993             layoutSet.setColorSchemeId(
994                 PropsValues.
995                     DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_COLOR_SCHEME_ID);
996 
997             updateLayoutSet = true;
998         }
999 
1000        if (Validator.isNotNull(
1001                PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_THEME_ID)) {
1002
1003            layoutSet.setWapThemeId(
1004                PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_THEME_ID);
1005
1006            updateLayoutSet = true;
1007        }
1008
1009        if (Validator.isNotNull(
1010                PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_COLOR_SCHEME_ID)) {
1011
1012            layoutSet.setWapColorSchemeId(
1013                PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_COLOR_SCHEME_ID);
1014
1015            updateLayoutSet = true;
1016        }
1017
1018        if (updateLayoutSet) {
1019            layoutSetLocalService.updateLayoutSet(layoutSet);
1020        }
1021    }
1022
1023    protected void addDefaultGuestPublicLayouts(Group group)
1024        throws PortalException, SystemException {
1025
1026        if (publicLARFile != null) {
1027            addDefaultGuestPublicLayoutsByLAR(group, publicLARFile);
1028        }
1029        else {
1030            addDefaultGuestPublicLayoutByProperties(group);
1031        }
1032    }
1033
1034    protected void addDefaultGuestPublicLayoutsByLAR(Group group, File larFile)
1035        throws PortalException, SystemException {
1036
1037        long defaultUserId = userLocalService.getDefaultUserId(
1038            group.getCompanyId());
1039
1040        Map<String, String[]> parameterMap = new HashMap<String, String[]>();
1041
1042        parameterMap.put(
1043            PortletDataHandlerKeys.CATEGORIES,
1044            new String[] {Boolean.TRUE.toString()});
1045        parameterMap.put(
1046            PortletDataHandlerKeys.PERMISSIONS,
1047            new String[] {Boolean.TRUE.toString()});
1048        parameterMap.put(
1049            PortletDataHandlerKeys.PORTLET_DATA,
1050            new String[] {Boolean.TRUE.toString()});
1051        parameterMap.put(
1052            PortletDataHandlerKeys.PORTLET_DATA_CONTROL_DEFAULT,
1053            new String[] {Boolean.TRUE.toString()});
1054        parameterMap.put(
1055            PortletDataHandlerKeys.PORTLET_SETUP,
1056            new String[] {Boolean.TRUE.toString()});
1057        parameterMap.put(
1058            PortletDataHandlerKeys.USER_PERMISSIONS,
1059            new String[] {Boolean.FALSE.toString()});
1060
1061        layoutLocalService.importLayouts(
1062            defaultUserId, group.getGroupId(), false, parameterMap, larFile);
1063    }
1064
1065    protected String getFriendlyURL(String friendlyURL) {
1066        return FriendlyURLNormalizer.normalize(friendlyURL);
1067    }
1068
1069    protected String getFriendlyURL(
1070            long companyId, long groupId, long classNameId, long classPK,
1071            String friendlyName, String friendlyURL)
1072        throws PortalException, SystemException {
1073
1074        friendlyURL = getFriendlyURL(friendlyURL);
1075
1076        if (Validator.isNull(friendlyURL)) {
1077            friendlyURL = StringPool.SLASH + getFriendlyURL(friendlyName);
1078
1079            String originalFriendlyURL = friendlyURL;
1080
1081            for (int i = 1;; i++) {
1082                try {
1083                    validateFriendlyURL(
1084                        companyId, groupId, classNameId, classPK, friendlyURL);
1085
1086                    break;
1087                }
1088                catch (GroupFriendlyURLException gfurle) {
1089                    int type = gfurle.getType();
1090
1091                    if (type == GroupFriendlyURLException.DUPLICATE) {
1092                        friendlyURL = originalFriendlyURL + i;
1093                    }
1094                    else {
1095                        friendlyURL = StringPool.SLASH + classPK;
1096
1097                        break;
1098                    }
1099                }
1100            }
1101        }
1102
1103        return friendlyURL;
1104    }
1105
1106    protected void initImportLARFile() {
1107        String publicLARFileName = PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUTS_LAR;
1108
1109        if (_log.isDebugEnabled()) {
1110            _log.debug("Reading public LAR file " + publicLARFileName);
1111        }
1112
1113        if (Validator.isNotNull(publicLARFileName)) {
1114            publicLARFile = new File(publicLARFileName);
1115
1116            if (!publicLARFile.exists()) {
1117                _log.error(
1118                    "Public LAR file " + publicLARFile + " does not exist");
1119
1120                publicLARFile = null;
1121            }
1122            else {
1123                if (_log.isDebugEnabled()) {
1124                    _log.debug("Using public LAR file " + publicLARFileName);
1125                }
1126            }
1127        }
1128    }
1129
1130    protected void unscheduleStaging(Group group) {
1131        try {
1132
1133            // Remote publishing
1134
1135            String groupName = StagingUtil.getSchedulerGroupName(
1136                DestinationNames.LAYOUTS_REMOTE_PUBLISHER, group.getGroupId());
1137
1138            List<SchedulerRequest> schedulerRequests =
1139                SchedulerEngineUtil.getScheduledJobs(groupName);
1140
1141            for (SchedulerRequest schedulerRequest : schedulerRequests) {
1142                SchedulerEngineUtil.unschedule(schedulerRequest.getTrigger());
1143            }
1144
1145            long liveGroupId = 0;
1146            long stagingGroupId = 0;
1147
1148            if (group.isStagingGroup()) {
1149                liveGroupId = group.getLiveGroupId();
1150
1151                stagingGroupId = group.getGroupId();
1152            }
1153            else if (group.hasStagingGroup()) {
1154                liveGroupId = group.getGroupId();
1155
1156                stagingGroupId = group.getStagingGroup().getGroupId();
1157            }
1158
1159            if ((liveGroupId != 0) && (stagingGroupId != 0)) {
1160
1161                // Publish to live
1162
1163                groupName = StagingUtil.getSchedulerGroupName(
1164                    DestinationNames.LAYOUTS_LOCAL_PUBLISHER, liveGroupId);
1165
1166                schedulerRequests = SchedulerEngineUtil.getScheduledJobs(
1167                    groupName);
1168
1169                for (SchedulerRequest schedulerRequest : schedulerRequests) {
1170                    SchedulerEngineUtil.unschedule(
1171                        schedulerRequest.getTrigger());
1172                }
1173
1174                // Copy from live
1175
1176                groupName = StagingUtil.getSchedulerGroupName(
1177                    DestinationNames.LAYOUTS_LOCAL_PUBLISHER, stagingGroupId);
1178
1179                schedulerRequests = SchedulerEngineUtil.getScheduledJobs(
1180                    groupName);
1181
1182                for (SchedulerRequest schedulerRequest : schedulerRequests) {
1183                    SchedulerEngineUtil.unschedule(
1184                        schedulerRequest.getTrigger());
1185                }
1186            }
1187        }
1188        catch (Exception e) {
1189            _log.error(
1190                "Unable to unschedule events for group: " + group.getGroupId());
1191        }
1192    }
1193
1194    protected void validateFriendlyURL(
1195            long companyId, long groupId, long classNameId, long classPK,
1196            String friendlyURL)
1197        throws PortalException, SystemException {
1198
1199        Company company = companyPersistence.findByPrimaryKey(companyId);
1200
1201        if (company.isSystem()) {
1202            return;
1203        }
1204
1205        if (Validator.isNull(friendlyURL)) {
1206            return;
1207        }
1208
1209        int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
1210
1211        if (exceptionType != -1) {
1212            throw new GroupFriendlyURLException(exceptionType);
1213        }
1214
1215        Group group = groupPersistence.fetchByC_F(companyId, friendlyURL);
1216
1217        if ((group != null) && (group.getGroupId() != groupId)) {
1218            throw new GroupFriendlyURLException(
1219                GroupFriendlyURLException.DUPLICATE);
1220        }
1221
1222        String groupIdFriendlyURL = friendlyURL.substring(1);
1223
1224        if (Validator.isNumber(groupIdFriendlyURL)) {
1225            long groupClassNameId = PortalUtil.getClassNameId(Group.class);
1226
1227            if (((classNameId != groupClassNameId) &&
1228                 (!groupIdFriendlyURL.equals(String.valueOf(classPK))) &&
1229                 (!PropsValues.USERS_SCREEN_NAME_ALLOW_NUMERIC)) ||
1230                ((classNameId == groupClassNameId) &&
1231                 (!groupIdFriendlyURL.equals(String.valueOf(groupId))))) {
1232
1233                GroupFriendlyURLException gfurle =
1234                    new GroupFriendlyURLException(
1235                        GroupFriendlyURLException.POSSIBLE_DUPLICATE);
1236
1237                gfurle.setKeywordConflict(groupIdFriendlyURL);
1238
1239                throw gfurle;
1240            }
1241        }
1242
1243        String screenName = friendlyURL.substring(1);
1244
1245        User user = userPersistence.fetchByC_SN(companyId, screenName);
1246
1247        if (user != null) {
1248            long userClassNameId = PortalUtil.getClassNameId(User.class);
1249
1250            if ((classNameId == userClassNameId) &&
1251                (classPK == user.getUserId())) {
1252            }
1253            else {
1254                throw new GroupFriendlyURLException(
1255                    GroupFriendlyURLException.DUPLICATE);
1256            }
1257        }
1258
1259        if (StringUtil.count(friendlyURL, StringPool.SLASH) > 1) {
1260            throw new GroupFriendlyURLException(
1261                GroupFriendlyURLException.TOO_DEEP);
1262        }
1263    }
1264
1265    protected void validateName(long groupId, long companyId, String name)
1266        throws PortalException, SystemException {
1267
1268        if ((Validator.isNull(name)) || (Validator.isNumber(name)) ||
1269            (name.indexOf(StringPool.COMMA) != -1) ||
1270            (name.indexOf(StringPool.STAR) != -1)) {
1271
1272            throw new GroupNameException();
1273        }
1274
1275        try {
1276            Group group = groupFinder.findByC_N(companyId, name);
1277
1278            if ((groupId <= 0) || (group.getGroupId() != groupId)) {
1279                throw new DuplicateGroupException();
1280            }
1281        }
1282        catch (NoSuchGroupException nsge) {
1283        }
1284    }
1285
1286    protected File publicLARFile;
1287
1288    private static Log _log = LogFactoryUtil.getLog(
1289        GroupLocalServiceImpl.class);
1290
1291    private Map<String, Group> _systemGroupsMap = new HashMap<String, Group>();
1292
1293}