/* * * Copyright (C) 2007-2015 Licensed to the Comunes Association (CA) under * one or more contributor license agreements (see COPYRIGHT for details). * The CA licenses this file to you under the GNU Affero General Public * License version 3, (the "License"); you may not use this file except in * compliance with the License. This file is part of kune. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package cc.kune.core.server.manager.impl; import java.util.List; import java.util.Set; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.PersistenceException; import org.apache.lucene.queryParser.QueryParser; import org.hibernate.exception.ConstraintViolationException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; import cc.kune.common.shared.i18n.I18nTranslationService; import cc.kune.core.client.errors.AccessViolationException; import cc.kune.core.client.errors.DefaultException; import cc.kune.core.client.errors.EmailAddressInUseException; import cc.kune.core.client.errors.GroupLongNameInUseException; import cc.kune.core.client.errors.GroupShortNameInUseException; import cc.kune.core.client.errors.ToolIsDefaultException; import cc.kune.core.client.errors.UserMustBeLoggedException; import cc.kune.core.server.manager.FileManager; import cc.kune.core.server.manager.GroupManager; import cc.kune.core.server.manager.LicenseManager; import cc.kune.core.server.manager.SearchResult; import cc.kune.core.server.manager.file.FileUtils; import cc.kune.core.server.mbean.MBeanRegistry; import cc.kune.core.server.persist.DataSourceKune; import cc.kune.core.server.persist.KuneTransactional; import cc.kune.core.server.properties.KuneBasicProperties; import cc.kune.core.server.properties.KuneProperties; import cc.kune.core.server.tool.ServerTool; import cc.kune.core.server.tool.ServerToolRegistry; import cc.kune.core.shared.SearcherConstants; import cc.kune.core.shared.domain.AdmissionType; import cc.kune.core.shared.domain.GroupListMode; import cc.kune.core.shared.domain.SocialNetworkVisibility; import cc.kune.core.shared.dto.GroupDTO; import cc.kune.core.shared.dto.GroupType; import cc.kune.domain.AccessLists; import cc.kune.domain.Content; import cc.kune.domain.Group; import cc.kune.domain.License; import cc.kune.domain.SocialNetwork; import cc.kune.domain.ToolConfiguration; import cc.kune.domain.User; import cc.kune.domain.finders.GroupFinder; import cc.kune.domain.finders.LicenseFinder; import cc.kune.domain.finders.UserFinder; import cc.kune.trash.server.TrashServerTool; // TODO: Auto-generated Javadoc /** * The Class GroupManagerDefault. * * @author danigb@gmail.com * @author vjrj@ourproject.org (Vicente J. Ruiz Jurado) */ @Singleton public class GroupManagerDefault extends DefaultManager<Group, Long> implements GroupManager, GroupManagerDefaultMBean { /** The file manager. */ private final FileManager fileManager; /** The finder. */ private final GroupFinder finder; /** The i18n. */ private final I18nTranslationService i18n; /** The kune properties. */ private final KuneProperties kuneProperties; /** The license finder. */ private final LicenseFinder licenseFinder; /** The license manager. */ private final LicenseManager licenseManager; /** The properties. */ private final KuneBasicProperties properties; /** The server tool registry. */ private final ServerToolRegistry serverToolRegistry; /** The sn cache. */ private final SocialNetworkCache snCache; /** The trash tool. */ private final Provider<TrashServerTool> trashTool; /** The user finder. */ private final UserFinder userFinder; /** * Instantiates a new group manager default. * * @param provider * the provider * @param finder * the finder * @param userFinder * the user finder * @param kuneProperties * the kune properties * @param properties * the properties * @param licenseManager * the license manager * @param licenseFinder * the license finder * @param fileManager * the file manager * @param serverToolRegistry * the server tool registry * @param trashTool * the trash tool * @param i18n * the i18n * @param snCache * the sn cache * @param mBeanRegistry * the m bean registry */ @Inject public GroupManagerDefault(@DataSourceKune final Provider<EntityManager> provider, final GroupFinder finder, final UserFinder userFinder, final KuneProperties kuneProperties, final KuneBasicProperties properties, final LicenseManager licenseManager, final LicenseFinder licenseFinder, final FileManager fileManager, final ServerToolRegistry serverToolRegistry, final Provider<TrashServerTool> trashTool, final I18nTranslationService i18n, final SocialNetworkCache snCache, final MBeanRegistry mBeanRegistry) { super(provider, Group.class); mBeanRegistry.registerAsMBean(this, GroupManagerDefaultMBean.MBEAN_OBJECT_NAME); this.finder = finder; this.userFinder = userFinder; this.kuneProperties = kuneProperties; this.properties = properties; this.licenseManager = licenseManager; this.licenseFinder = licenseFinder; this.fileManager = fileManager; this.serverToolRegistry = serverToolRegistry; this.trashTool = trashTool; this.i18n = i18n; this.snCache = snCache; } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#changeDefLicense(cc.kune.domain * .User, cc.kune.domain.Group, java.lang.String) */ @Override public void changeDefLicense(final User user, final Group group, final String licName) { final License license = licenseFinder.findByShortName(licName); if (license == null) { throw new ServerManagerException("Unknown license"); } group.setDefaultLicense(license); } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#changeWsTheme(cc.kune.domain.User, * cc.kune.domain.Group, java.lang.String) */ @Override public void changeWsTheme(final User user, final Group group, final String theme) throws AccessViolationException { // TODO: check theme group.setWorkspaceTheme(theme); } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#checkIfLongNameAreInUse(java.lang * .String) */ @Override public void checkIfLongNameAreInUse(final String longName) { if (finder.countByLongName(longName) != 0) { throw new GroupLongNameInUseException(); } } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#checkIfShortNameAreInUse(java. * lang.String) */ @Override public void checkIfShortNameAreInUse(final String shortName) { if (finder.countByShortName(shortName) != 0) { throw new GroupShortNameInUseException(); } } @Override public void reIndex() { // NOTE: here we do not use KuneTransactional because hibernate-search use plain JPA transaction and we get into a deadlock super.reIndex(); } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#clearGroupBackImage(cc.kune.domain * .Group) */ @Override public void clearGroupBackImage(final Group group) { final String file = group.getBackgroundImage(); if (file != null) { fileManager.rm(FileUtils.groupToDir(group.getShortName()), file); } group.setBackgroundImage(null); group.setBackgroundMime(null); } /* * (non-Javadoc) * * @see cc.kune.core.server.manager.GroupManager#count() */ @Override @KuneTransactional public Long count() { return finder.count(); // NOTE The problem with super.size, is that uses JPA normal transactions // (no KuneTransactional) and // can block if it's under a KuneTransactional method. Normal JPA // transactions don't use the Guice Units of work // return super.size(); } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#createGroup(cc.kune.domain.Group, * cc.kune.domain.User, java.lang.String) */ @Override public Group createGroup(final Group group, final User user, final String publicDescrip) throws GroupShortNameInUseException, GroupLongNameInUseException, UserMustBeLoggedException { checkIfShortNameAreInUse(group.getShortName()); checkIfLongNameAreInUse(group.getLongName()); final String defaultSiteWorkspaceTheme = kuneProperties.get(KuneProperties.WS_THEMES_DEF); if (User.isKnownUser(user)) { setAdmissionType(group); final String licName = group.getDefaultLicense().getShortName(); final License license = licenseFinder.findByShortName(licName); group.setDefaultLicense(license); group.setWorkspaceTheme(defaultSiteWorkspaceTheme); final boolean isClosed = group.getGroupType().equals(GroupType.CLOSED); initSocialNetwork(group, user.getUserGroup(), getDefGroupMode(isClosed), getDefSNVisibility(isClosed)); final String title = i18n.t("About [%s]", group.getLongName()); initGroup(user, group, serverToolRegistry.getToolsRegisEnabledForGroups(), title, publicDescrip); snCache.expire(user.getUserGroup()); return group; } else { throw new UserMustBeLoggedException(); } } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#createUserGroup(cc.kune.domain * .User) */ @Override public Group createUserGroup(final User user) throws GroupShortNameInUseException, EmailAddressInUseException { return createUserGroup(user, true); } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#createUserGroup(cc.kune.domain * .User, boolean) */ @Override public Group createUserGroup(final User user, final boolean wantPersonalHomepage) throws GroupShortNameInUseException, EmailAddressInUseException { final String defaultSiteWorkspaceTheme = kuneProperties.get(KuneProperties.WS_THEMES_DEF); final License licenseDef = licenseManager.getDefLicense(); final Group userGroup = new Group(user.getShortName(), user.getName(), licenseDef, GroupType.PERSONAL); User userSameEmail = null; try { userSameEmail = userFinder.findByEmail(user.getEmail()); } catch (final NoResultException e) { // Ok, no more with this email } if (userSameEmail != null) { throw new EmailAddressInUseException(); } userGroup.setAdmissionType(AdmissionType.Closed); userGroup.setWorkspaceTheme(defaultSiteWorkspaceTheme); userGroup.setDefaultContent(null); user.setUserGroup(userGroup); initSocialNetwork(userGroup, userGroup, GroupListMode.EVERYONE, SocialNetworkVisibility.anyone); final String title = i18n.t("[%s] Bio", user.getName()); final String body = i18n.t("This is [%s]'s bio, currently empty", user.getName()); try { initGroup(user, userGroup, wantPersonalHomepage ? serverToolRegistry.getToolsRegisEnabledForUsers() : ServerToolRegistry.emptyToolList, title, body); super.persist(user, User.class); } catch (final PersistenceException e) { if (e.getCause() instanceof ConstraintViolationException) { throw new GroupShortNameInUseException(); } throw e; } return userGroup; } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#findAdminInGroups(java.lang.Long) */ @Override public Set<Group> findAdminInGroups(final Long groupId) { return finder.findAdminInGroups(groupId); } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#findByShortName(java.lang.String) */ @Override public Group findByShortName(final String shortName) { return finder.findByShortName(shortName); } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#findCollabInGroups(java.lang.Long) */ @Override public Set<Group> findCollabInGroups(final Long groupId) { return finder.findCollabInGroups(groupId); } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#findEnabledTools(java.lang.Long) */ @Override public List<String> findEnabledTools(final Long id) { return finder.findEnabledTools(id); } /** * Gets the def group mode. * * @param isClosed * the is closed * @return the def group mode */ private GroupListMode getDefGroupMode(final boolean isClosed) { return isClosed ? GroupListMode.NORMAL : GroupListMode.EVERYONE; } /** * Gets the def sn visibility. * * @param isClosed * the is closed * @return the def sn visibility */ private SocialNetworkVisibility getDefSNVisibility(final boolean isClosed) { return isClosed ? SocialNetworkVisibility.onlymembers : SocialNetworkVisibility.anyone; } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#getGroupOfUserWithId(java.lang * .Long) */ @Override public Group getGroupOfUserWithId(final Long userId) { return userId != null ? find(User.class, userId).getUserGroup() : null; } /* * (non-Javadoc) * * @see cc.kune.core.server.manager.GroupManager#getSiteDefaultGroup() */ @Override public Group getSiteDefaultGroup() { final String shortName = properties.getDefaultSiteShortName(); return findByShortName(shortName); } /** * Inits the group. * * @param user * the user * @param group * the group * @param toolsToEnable * the tools to enable * @param vars * the vars * @throws GroupShortNameInUseException * the group short name in use exception */ private void initGroup(final User user, final Group group, final List<String> toolsToEnable, final Object... vars) throws GroupShortNameInUseException { try { persist(group); } catch (final IllegalStateException e) { e.printStackTrace(); } catch (final PersistenceException e) { if (e.getCause() instanceof ConstraintViolationException) { throw new GroupShortNameInUseException(); } throw e; } for (final ServerTool tool : serverToolRegistry.all()) { if (toolsToEnable.contains(tool.getName())) { tool.initGroup(user, group, vars); } } // Init always the trash initTrash(group); } /** * Inits the social network. * * @param group * the group * @param userGroup * the user group * @param publicVisibility * the public visibility * @param snVisibility * the sn visibility */ private void initSocialNetwork(final Group group, final Group userGroup, final GroupListMode publicVisibility, final SocialNetworkVisibility snVisibility) { final SocialNetwork network = setSocialNetwork(group, publicVisibility, snVisibility); if (!group.getGroupType().equals(GroupType.ORPHANED_PROJECT)) { network.addAdmin(userGroup); network.getAccessLists().getEditors().setMode(GroupListMode.NOBODY); } } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#initTrash(cc.kune.domain.Group) */ @Override public void initTrash(final Group group) { trashTool.get().initGroup(group); } /* * (non-Javadoc) * * @see cc.kune.core.server.manager.GroupManager#search(java.lang.String) */ @Override public SearchResult<Group> search(final String search) { return this.search(search, null, null); } /* * (non-Javadoc) * * @see cc.kune.core.server.manager.GroupManager#search(java.lang.String, * java.lang.Integer, java.lang.Integer) */ @Override // // @KuneTransactional public SearchResult<Group> search(final String search, final Integer firstResult, final Integer maxResults) { // Wildcard is not allowed in the first character of the query final String escapedQuery = QueryParser.escape(search) + SearcherConstants.WILDCARD; return super.search(new String[] { escapedQuery, escapedQuery, escapedQuery }, new String[] { "longName", "shortName", "publicDesc" }, firstResult, maxResults); } /** * Sets the admission type. * * @param group * the new admission type */ private void setAdmissionType(final Group group) { final GroupType groupType = group.getGroupType(); if (groupType.equals(GroupType.COMMUNITY)) { group.setAdmissionType(AdmissionType.Open); } else { if (groupType.equals(GroupType.CLOSED)) { group.setAdmissionType(AdmissionType.Closed); } else if (groupType.equals(GroupType.ORGANIZATION)) { group.setAdmissionType(AdmissionType.Moderated); } else if (groupType.equals(GroupType.PROJECT)) { group.setAdmissionType(AdmissionType.Moderated); } else if (groupType.equals(GroupType.ORPHANED_PROJECT)) { group.setAdmissionType(AdmissionType.Open); } } } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#setDefaultContent(java.lang.String * , cc.kune.domain.Content) */ @Override public void setDefaultContent(final String groupShortName, final Content content) { final Group group = findByShortName(groupShortName); group.setDefaultContent(content); } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#setGroupBackgroundImage(cc.kune * .domain.Group, java.lang.String, java.lang.String) */ @Override public void setGroupBackgroundImage(final Group group, final String backgroundFileName, final String mime) { clearGroupBackImage(group); group.setBackgroundImage(backgroundFileName); group.setBackgroundMime(mime); } /** * Sets the social network. * * @param group * the group * @param publicVisibility * the public visibility * @param snVisibility * the sn visibility * @return the social network */ private SocialNetwork setSocialNetwork(final Group group, final GroupListMode publicVisibility, final SocialNetworkVisibility snVisibility) { final SocialNetwork network = group.getSocialNetwork(); final AccessLists lists = network.getAccessLists(); lists.getViewers().setMode(publicVisibility); network.setVisibility(snVisibility); return network; } /* * (non-Javadoc) * * @see * cc.kune.core.server.manager.GroupManager#setToolEnabled(cc.kune.domain. * User, java.lang.String, java.lang.String, boolean) */ @Override public void setToolEnabled(final User userLogged, final String groupShortName, final String tool, final boolean enabled) throws ToolIsDefaultException { final Group group = findByShortName(groupShortName); if (group.getDefaultContent().getStateToken().getTool().equals(tool) && !enabled) { throw new ToolIsDefaultException(); } ToolConfiguration toolConfiguration = group.getToolConfiguration(tool); if (toolConfiguration == null) { toolConfiguration = serverToolRegistry.get(tool).initGroup(userLogged, group).getToolConfiguration( tool); } toolConfiguration.setEnabled(enabled); } /* * (non-Javadoc) * * @see cc.kune.core.server.manager.GroupManager#update(java.lang.Long, * cc.kune.core.shared.dto.GroupDTO) */ @Override public Group update(final Long groupId, final GroupDTO groupDTO) { final Group group = find(groupId); final String shortName = groupDTO.getShortName(); final String longName = groupDTO.getLongName(); if (!longName.equals(group.getLongName())) { checkIfLongNameAreInUse(longName); group.setLongName(longName); } if (!shortName.equals(group.getShortName())) { checkIfShortNameAreInUse(shortName); final String oldDir = kuneProperties.get(KuneProperties.UPLOAD_LOCATION) + FileUtils.groupToDir(group.getShortName()); final String newDir = kuneProperties.get(KuneProperties.UPLOAD_LOCATION) + FileUtils.groupToDir(shortName); if (fileManager.exists(oldDir)) { if (fileManager.exists(newDir)) { throw new DefaultException("Destination group directory exists"); } fileManager.mv(oldDir, newDir); } group.setShortName(shortName); } group.setGroupType(groupDTO.getGroupType()); setAdmissionType(group); final boolean isClosed = group.getGroupType().equals(GroupType.CLOSED); setSocialNetwork(group, getDefGroupMode(isClosed), getDefSNVisibility(isClosed)); persist(group); snCache.expire(group); return group; } }