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