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