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