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