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