/** * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * <p/> * This is free software;you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation;either version2.1of * the License,or(at your option)any later version. * <p/> * This software 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 * Lesser General Public License for more details. * <p/> * You should have received a copy of the GNU Lesser General Public * License along with this software;if not,write to the Free * Software Foundation,Inc.,51 Franklin St,Fifth Floor,Boston,MA * 02110-1301 USA,or see the FSF site:http://www.fsf.org. */ package com.xpn.xwiki.plugin.spacemanager.impl; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.Iterator; import java.util.List; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.velocity.VelocityContext; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.xwiki.model.reference.DocumentReference; import com.xpn.xwiki.XWiki; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.XWikiException; import com.xpn.xwiki.api.Api; import com.xpn.xwiki.doc.XWikiDocument; import com.xpn.xwiki.objects.BaseObject; import com.xpn.xwiki.objects.LargeStringProperty; import com.xpn.xwiki.objects.StringProperty; import com.xpn.xwiki.objects.classes.BaseClass; import com.xpn.xwiki.plugin.XWikiDefaultPlugin; import com.xpn.xwiki.plugin.XWikiPluginInterface; import com.xpn.xwiki.plugin.mailsender.Mail; import com.xpn.xwiki.plugin.mailsender.MailSenderPlugin; import com.xpn.xwiki.plugin.spacemanager.api.Space; import com.xpn.xwiki.plugin.spacemanager.api.SpaceManager; import com.xpn.xwiki.plugin.spacemanager.api.SpaceManagerException; import com.xpn.xwiki.plugin.spacemanager.api.SpaceManagerExtension; import com.xpn.xwiki.plugin.spacemanager.api.SpaceManagers; import com.xpn.xwiki.plugin.spacemanager.api.SpaceUserProfile; import com.xpn.xwiki.plugin.spacemanager.plugin.SpaceManagerPluginApi; import com.xpn.xwiki.render.XWikiVelocityRenderer; import com.xpn.xwiki.store.XWikiHibernateBaseStore.HibernateCallback; import com.xpn.xwiki.user.api.XWikiGroupService; /** * Space manager plug-in implementation class. Manages {@link Space} spaces * * @version $Id$ */ public class SpaceManagerImpl extends XWikiDefaultPlugin implements SpaceManager { public final static String SPACEMANAGER_EXTENSION_CFG_PROP = "xwiki.spacemanager.extension"; public final static String SPACEMANAGER_PROTECTED_SUBSPACES_PROP = "xwiki.spacemanager.protectedsubspaces"; public final static String SPACEMANAGER_DEFAULT_PROTECTED_SUBSPACES = ""; public final static String SPACEMANAGER_DEFAULT_EXTENSION = "org.xwiki.plugin.spacemanager.impl.SpaceManagerExtensionImpl"; public final static String SPACEMANAGER_DEFAULT_MAIL_NOTIFICATION = "1"; /** * Log object to log messages in this class. */ private static final Log LOG = LogFactory.getLog(SpaceManagerImpl.class); /** * The extension that defines specific functions for this space manager */ protected SpaceManagerExtension spaceManagerExtension; protected boolean mailNotification; /** * Space manager constructor * * @param name * @param className * @param context */ public SpaceManagerImpl(String name, String className, XWikiContext context) { super(name, className, context); String mailNotificationCfg = context.getWiki().Param("xwiki.spacemanager.mailnotification", SpaceManagerImpl.SPACEMANAGER_DEFAULT_MAIL_NOTIFICATION).trim(); mailNotification = "1".equals(mailNotificationCfg); } /** * {@inheritDoc} */ public void flushCache() { super.flushCache(); } /** * @param context Xwiki context * @return Returns the Space Class as defined by the extension * @throws XWikiException */ protected BaseClass getSpaceClass(XWikiContext context) throws XWikiException { XWikiDocument doc; XWiki xwiki = context.getWiki(); boolean needsUpdate = false; try { doc = xwiki.getDocument(getSpaceClassName(), context); } catch (Exception e) { doc = new XWikiDocument(); doc.setFullName(getSpaceClassName()); needsUpdate = true; } BaseClass bclass = doc.getxWikiClass(); bclass.setName(getSpaceClassName()); needsUpdate |= bclass.addTextField(SpaceImpl.SPACE_DISPLAYTITLE, "Display Name", 64); needsUpdate |= bclass.addTextAreaField(SpaceImpl.SPACE_DESCRIPTION, "Description", 45, 4); needsUpdate |= bclass.addTextField(SpaceImpl.SPACE_TYPE, "Group or plain space", 32); needsUpdate |= bclass.addTextField(SpaceImpl.SPACE_URLSHORTCUT, "URL Shortcut", 40); needsUpdate |= bclass.addStaticListField(SpaceImpl.SPACE_POLICY, "Membership Policy", 1, false, "open=Open membership|closed=Closed membership", "radio"); needsUpdate |= bclass .addStaticListField( SpaceImpl.SPACE_LANGUAGE, "Language", "en=English|zh=Chinese|nl=Dutch|fr=French|de=German|it=Italian|jp=Japanese|kr=Korean|po=Portuguese|ru=Russian|sp=Spanish"); String content = doc.getContent(); if ((content == null) || (content.equals(""))) { needsUpdate = true; doc.setContent("1 XWikiSpaceClass"); } if (needsUpdate) xwiki.saveDocument(doc, context); return bclass; } /** * {@inheritDoc} */ public String getSpaceTypeName() { return getSpaceManagerExtension().getSpaceTypeName(); } /** * {@inheritDoc} */ public String getSpaceClassName() { return getSpaceManagerExtension().getSpaceClassName(); } /** * Checks if this space manager has custom mapping * * @return */ public boolean hasCustomMapping() { return getSpaceManagerExtension().hasCustomMapping(); } /** * {@inheritDoc} */ public void init(XWikiContext context) { try { getSpaceManagerExtension(context); getSpaceManagerExtension().init(this, context); SpaceManagers.addSpaceManager(this); getSpaceClass(context); SpaceUserProfileImpl.getSpaceUserProfileClass(context); // Dirty migration of spaces potential corrupted XWiki.XWikiGlobalRights objects. migrateSpaceCorruptedRightsData(context); } catch (Exception e) { LOG.error("Error initializing plugin for main database", e); } } /** * {@inheritDoc} */ public void virtualInit(XWikiContext context) { try { getSpaceClass(context); getSpaceManagerExtension().virtualInit(this, context); // Dirty migration of spaces potential corrupted XWiki.XWikiGlobalRights objects. migrateSpaceCorruptedRightsData(context); } catch (Exception e) { LOG.error("Error initializing plugin for database [" + context.getDatabase() + "]", e); } } /** * Migrate wrong data created by spacemanager plugin versions < 1.0.2 or 1.1.1 or 1.2 * The plugin used to create users and groups properties of XWiki.XWikiGlobalRights objects as * StringProperty instead of LargeStringProperty, thus making it impossible to save * a Space WebPreferences document from the object editor (see http://jira.xwiki.org/jira/browse/XPSM-12) * * @since 1.0.2 * @since 1.1.1 * @since 1.2 * @param context * @throws SpaceManagerException */ private void migrateSpaceCorruptedRightsData(XWikiContext context) throws SpaceManagerException { try { context.getWiki().getHibernateStore().executeWrite(context, true, new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Query q = session.createQuery("select s from BaseObject o, StringProperty s where o.className like 'XWiki.XWiki%Rights' and o.id=s.id and (s.name='users' or s.name='groups')"); List lst = q.list(); if (lst.size()==0) return null; LOG.warn("[Migrating corrupted rights properties (see http://jira.xwiki.org/jira/browse/XPSM-12)"); List lst2 = new ArrayList(lst.size()); for (Iterator it=lst.iterator(); it.hasNext(); ) { StringProperty sp = (StringProperty) it.next(); LargeStringProperty lsp = new LargeStringProperty(); lsp.setId(sp.getId()); lsp.setName(sp.getName()); lsp.setValue(sp.getValue()); lst2.add(lsp); } for (Iterator it=lst.iterator(); it.hasNext(); ) session.delete(it.next()); for (Iterator it=lst2.iterator(); it.hasNext(); ) session.save(it.next()); return null; } }); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public Api getPluginApi(XWikiPluginInterface plugin, XWikiContext context) { return new SpaceManagerPluginApi((SpaceManager) plugin, context); } /** * {@inheritDoc} */ public SpaceManagerExtension getSpaceManagerExtension(XWikiContext context) throws SpaceManagerException { if (spaceManagerExtension == null) { String extensionName = context.getWiki().Param(SPACEMANAGER_EXTENSION_CFG_PROP, SPACEMANAGER_DEFAULT_EXTENSION); try { if (extensionName != null) { spaceManagerExtension = (SpaceManagerExtension) Class.forName(extensionName).newInstance(); } } catch (Throwable e) { try { spaceManagerExtension = (SpaceManagerExtension) Class.forName(SPACEMANAGER_DEFAULT_EXTENSION) .newInstance(); } catch (Throwable e2) { } } } if (spaceManagerExtension == null) { spaceManagerExtension = new SpaceManagerExtensionImpl(); } return spaceManagerExtension; } public SpaceManagerExtension getSpaceManagerExtension() { return spaceManagerExtension; } /** * {@inheritDoc} */ public String getName() { return "spacemanager"; } private Object notImplemented() throws SpaceManagerException { throw new SpaceManagerException(SpaceManagerException.MODULE_PLUGIN_SPACEMANAGER, SpaceManagerException.ERROR_XWIKI_NOT_IMPLEMENTED, "not implemented"); } /** * {@inheritDoc} */ public String getSpaceWikiName(String spaceTitle, boolean unique, XWikiContext context) { return getSpaceManagerExtension().getSpaceWikiName(spaceTitle, unique, context); } /** * @param spaceName The name of the space * @return the name of the space document for a specific space */ protected String getSpaceDocumentName(String spaceName) { return spaceName + ".WebPreferences"; } /** * {@inheritDoc} */ public String[] getProtectedSubSpaces(XWikiContext context) { String protectedSubSpaces = context.getWiki().Param(SPACEMANAGER_PROTECTED_SUBSPACES_PROP, SPACEMANAGER_DEFAULT_PROTECTED_SUBSPACES); if ((protectedSubSpaces != null) && (!protectedSubSpaces.equals(""))) { return protectedSubSpaces.split(","); } else { return new String[0]; } } /** * Gives a group certain rights over a space * * @param spaceName Name of the space * @param groupName Name of the group that will have the value * @param level Access level * @param allow True if the right is allow, deny if not */ protected boolean addRightToGroup(String spaceName, String groupName, String level, boolean allow, boolean global, XWikiContext context) throws XWikiException { final String rightsClass = global ? "XWiki.XWikiGlobalRights" : "XWiki.XWikiRights"; final String prefDocName = spaceName + ".WebPreferences"; final String groupsField = "groups"; final String levelsField = "levels"; final String allowField = "allow"; XWikiDocument prefDoc; prefDoc = context.getWiki().getDocument(prefDocName, context); // checks to see if the right is not already given boolean exists = false; boolean isUpdated = false; int indx = -1; boolean foundlevel = false; int allowInt; if (allow) allowInt = 1; else allowInt = 0; List objs = prefDoc.getObjects(rightsClass); if (objs != null) { for (int i = 0; i < objs.size(); i++) { BaseObject bobj = (BaseObject) objs.get(i); if (bobj == null) continue; String groups = bobj.getLargeStringValue(groupsField); String levels = bobj.getStringValue(levelsField); int allowDeny = bobj.getIntValue(allowField); boolean allowdeny = (bobj.getIntValue(allowField) == 1); String[] levelsarray = levels.split(" ,|"); String[] groupsarray = groups.split(" ,|"); if (ArrayUtils.contains(groupsarray, groupName)) { exists = true; if (!foundlevel) indx = i; if (ArrayUtils.contains(levelsarray, level)) { foundlevel = true; if (allowInt == allowDeny) { isUpdated = true; break; } } } } } // sets the rights. the aproach is to break rules/levels in as many // XWikiRigts elements so // we don't have to handle lots of situation when we change rights if (!exists) { BaseObject bobj = new BaseObject(); bobj.setClassName(rightsClass); bobj.setName(prefDoc.getFullName()); bobj.setLargeStringValue(groupsField, groupName); bobj.setStringValue(levelsField, level); bobj.setIntValue(allowField, allowInt); prefDoc.addObject(rightsClass, bobj); context.getWiki().saveDocument(prefDoc, context); return true; } else { if (isUpdated) { return true; } else { BaseObject bobj = (BaseObject) objs.get(indx); String groups = bobj.getLargeStringValue(groupsField); String levels = bobj.getStringValue(levelsField); String[] levelsarray = levels.split(" ,|"); String[] groupsarray = groups.split(" ,|"); if (levelsarray.length == 1 && groupsarray.length == 1 && levelsarray[0] == level) { // if there is only this group and this level in the rule // update this rule } else { // if there are more groups/levels, extract this one(s) bobj = new BaseObject(); bobj.setName(prefDoc.getFullName()); bobj.setClassName(rightsClass); bobj.setStringValue(levelsField, level); bobj.setIntValue(allowField, allowInt); bobj.setLargeStringValue(groupsField, groupName); } prefDoc.addObject(rightsClass, bobj); context.getWiki().saveDocument(prefDoc, context); return true; } } } /** * Gives a group certain rights over a space * * @param spaceName Name of the space * @param groupName Name of the group that will have the value * @param level Access level * @param allow True if the right is allow, deny if not */ protected boolean removeRightFromGroup(String spaceName, String groupName, String level, boolean allow, boolean global, XWikiContext context) throws XWikiException { final String rightsClass = global ? "XWiki.XWikiGlobalRights" : "XWiki.XWikiRights"; final String prefDocName = spaceName + ".WebPreferences"; final String groupsField = "groups"; final String levelsField = "levels"; final String allowField = "allow"; XWikiDocument prefDoc; prefDoc = context.getWiki().getDocument(prefDocName, context); boolean foundlevel = false; int allowInt; if (allow) allowInt = 1; else allowInt = 0; List objs = prefDoc.getObjects(rightsClass); if (objs != null) { for (int i = 0; i < objs.size(); i++) { BaseObject bobj = (BaseObject) objs.get(i); if (bobj == null) continue; String groups = bobj.getLargeStringValue(groupsField); String levels = bobj.getStringValue(levelsField); int allowDeny = bobj.getIntValue(allowField); boolean allowdeny = (bobj.getIntValue(allowField) == 1); String[] levelsarray = levels.split(" ,|"); String[] groupsarray = groups.split(" ,|"); if (ArrayUtils.contains(groupsarray, groupName)) { if (!foundlevel) if (ArrayUtils.contains(levelsarray, level)) { foundlevel = true; if (allowInt == allowDeny) { prefDoc.removeObject(bobj); context.getWiki().saveDocument(prefDoc, context); return true; } } } } } return false; } /** * {@inheritDoc} */ public void setSpaceRights(Space newspace, XWikiContext context) throws SpaceManagerException { // Set admin edit rights on group prefs try { addRightToGroup(newspace.getSpaceName(), getAdminGroupName(newspace.getSpaceName()), "edit", true, false, context); // Set admin admin rights on group prefs addRightToGroup(newspace.getSpaceName(), getAdminGroupName(newspace.getSpaceName()), "admin", true, true, context); } catch (XWikiException e) { throw new SpaceManagerException(e); } String[] subSpaces = getProtectedSubSpaces(context); for (int i = 0; i < subSpaces.length; i++) { setSubSpaceRights(newspace, subSpaces[i], context); } } /** * {@inheritDoc} */ public void updateSpaceRights(Space space, String oldPolicy, String newPolicy, XWikiContext context) throws SpaceManagerException { try { if (oldPolicy.equals(newPolicy)) return; String[] subSpaces = getProtectedSubSpaces(context); for (int i = 0; i < subSpaces.length; i++) { if (newPolicy.equals("closed")) { addRightToGroup(subSpaces[i] + "_" + space.getSpaceName(), getMemberGroupName(space.getSpaceName()), "view", true, true, context); addRightToGroup(subSpaces[i] + "_" + space.getSpaceName(), getMemberGroupName(space.getSpaceName()), "comment", true, true, context); } else if (newPolicy.equals("open")) { removeRightFromGroup(subSpaces[i] + "_" + space.getSpaceName(), getMemberGroupName(space.getSpaceName()), "view", true, true, context); removeRightFromGroup(subSpaces[i] + "_" + space.getSpaceName(), getMemberGroupName(space.getSpaceName()), "comment", true, true, context); } } } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public void setSubSpaceRights(Space space, String subSpace, XWikiContext context) throws SpaceManagerException { try { if ((subSpace != null) && (!subSpace.equals(""))) { // Set admin edit rights on Messages group prefs addRightToGroup(subSpace + "_" + space.getSpaceName(), getMemberGroupName(space .getSpaceName()), "edit", true, true, context); // Set admin admin rights on Messages group prefs addRightToGroup(subSpace + "_" + space.getSpaceName(), getAdminGroupName(space .getSpaceName()), "admin", true, true, context); // Set admin admin rights on Messages group prefs addRightToGroup(subSpace + "_" + space.getSpaceName(), getAdminGroupName(space .getSpaceName()), "edit", true, false, context); if ("closed".equals(space.getPolicy())) { addRightToGroup(subSpace + "_" + space.getSpaceName(), getMemberGroupName(space.getSpaceName()), "view", true, true, context); addRightToGroup(subSpace + "_" + space.getSpaceName(), getMemberGroupName(space.getSpaceName()), "comment", true, true, context); } } } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public Space createSpace(String spaceTitle, XWikiContext context) throws SpaceManagerException { // Init out space object by creating the space // this will throw an exception when the space exists Space newspace = newSpace(null, spaceTitle, true, context); // execute precreate actions try { getSpaceManagerExtension().preCreateSpace(newspace.getSpaceName(), context); } catch (SpaceManagerException e) { throw new SpaceManagerException(SpaceManagerException.MODULE_PLUGIN_SPACEMANAGER, SpaceManagerException.ERROR_SPACE_CREATION_ABORTED_BY_EXTENSION, "Space creation aborted by extension", e); } // Make sure we set the type newspace.setType(getSpaceTypeName()); try { newspace.saveWithProgrammingRights(); // we need to add the creator as a member and as an admin addAdmin(newspace.getSpaceName(), context.getUser(), context); addMember(newspace.getSpaceName(), context.getUser(), context); setSpaceRights(newspace, context); // execute post space creation getSpaceManagerExtension().postCreateSpace(newspace.getSpaceName(), context); } catch (XWikiException e) { throw new SpaceManagerException(e); } sendMail(SpaceAction.CREATE, newspace, context); // this should be in // the extension's // postcreate return newspace; } /** * {@inheritDoc} */ public Space createSpaceFromTemplate(String spaceTitle, String templateSpaceName, XWikiContext context) throws SpaceManagerException { // Init out space object by creating the space // this will throw an exception when the space exists Space newspace = newSpace(null, spaceTitle, false, context); // execute precreate actions try { getSpaceManagerExtension().preCreateSpace(newspace.getSpaceName(), context); } catch (SpaceManagerException e) { throw new SpaceManagerException(SpaceManagerException.MODULE_PLUGIN_SPACEMANAGER, SpaceManagerException.ERROR_SPACE_CREATION_ABORTED_BY_EXTENSION, "Space creation aborted by extension", e); } // Make sure this space does not already exist if (!newspace.isNew()) throw new SpaceManagerException(SpaceManagerException.MODULE_PLUGIN_SPACEMANAGER, SpaceManagerException.ERROR_SPACE_ALREADY_EXISTS, "Space already exists"); // Copy over template data over our current data try { context.getWiki().copyWikiWeb(templateSpaceName, context.getDatabase(), context.getDatabase(), null, context); } catch (XWikiException e) { throw new SpaceManagerException(e); } // Make sure we set the type newspace.setType(getSpaceTypeName()); newspace.setDisplayTitle(spaceTitle); newspace.setCreator(context.getUser()); newspace.setCreationDate(new Date()); try { newspace.saveWithProgrammingRights(); // we need to add the creator as a member and as an admin addAdmin(newspace.getSpaceName(), context.getUser(), context); addMember(newspace.getSpaceName(), context.getUser(), context); setSpaceRights(newspace, context); // execute post space creation getSpaceManagerExtension().postCreateSpace(newspace.getSpaceName(), context); } catch (XWikiException e) { throw new SpaceManagerException(e); } sendMail(SpaceAction.CREATE, newspace, context); return newspace; } /** * {@inheritDoc} */ public Space createSpaceFromApplication(String spaceTitle, String applicationName, XWikiContext context) throws SpaceManagerException { notImplemented(); return null; } /** * {@inheritDoc} */ public Space createSpaceFromRequest(String templateSpaceName, XWikiContext context) throws SpaceManagerException { // Init out space object by creating the space // this will throw an exception when the space exists String spaceTitle = context.getRequest().get( spaceManagerExtension.getSpaceClassName() + "_0_displayTitle"); if (spaceTitle == null) { throw new SpaceManagerException(SpaceManagerException.MODULE_PLUGIN_SPACEMANAGER, SpaceManagerException.ERROR_SPACE_TITLE_MISSING, "Space title is missing"); } Space newspace = newSpace(null, spaceTitle, true, context); // execute precreate actions try { getSpaceManagerExtension().preCreateSpace(newspace.getSpaceName(), context); } catch (SpaceManagerException e) { throw new SpaceManagerException(SpaceManagerException.MODULE_PLUGIN_SPACEMANAGER, SpaceManagerException.ERROR_SPACE_CREATION_ABORTED_BY_EXTENSION, "Space creation aborted by extension", e); } newspace.updateSpaceFromRequest(); if (!newspace.validateSpaceData()) throw new SpaceManagerException(SpaceManagerException.MODULE_PLUGIN_SPACEMANAGER, SpaceManagerException.ERROR_SPACE_DATA_INVALID, "Space data is not valid"); // Copy over template data over our current data if (templateSpaceName != null) { try { List list = context.getWiki().getStore().searchDocumentsNames( "where doc.web='" + templateSpaceName + "'", context); for (Iterator it = list.iterator(); it.hasNext();) { String docname = (String) it.next(); XWikiDocument doc = context.getWiki().getDocument(docname, context); DocumentReference newDocumentReference = new DocumentReference(doc.getDocumentReference().getWikiReference().getName(), newspace.getSpaceName(), doc.getName()); context.getWiki().copyDocument(doc.getDocumentReference(), newDocumentReference, null, true, false, true, context); } } catch (XWikiException e) { throw new SpaceManagerException(e); } } // Make sure we set the type newspace.setType(getSpaceTypeName()); // we need to do it twice because data could have been overwritten by // copyWikiWeb newspace.updateSpaceFromRequest(); newspace.setCreator(context.getUser()); newspace.setCreationDate(new Date()); try { newspace.saveWithProgrammingRights(); // we need to add the creator as a member and as an admin addAdmin(newspace.getSpaceName(), context.getUser(), context); addMember(newspace.getSpaceName(), context.getUser(), context); setSpaceRights(newspace, context); // execute precreate actions getSpaceManagerExtension().postCreateSpace(newspace.getSpaceName(), context); } catch (XWikiException e) { throw new SpaceManagerException(e); } sendMail(SpaceAction.CREATE, newspace, context); return newspace; } protected Space newSpace(String spaceName, String spaceTitle, boolean create, XWikiContext context) throws SpaceManagerException { return new SpaceImpl(spaceName, spaceTitle, create, this, context); } /** * {@inheritDoc} */ public Space createSpaceFromRequest(XWikiContext context) throws SpaceManagerException { return createSpaceFromRequest(null, context); } /** * {@inheritDoc} */ public void deleteSpace(String spaceName, boolean deleteData, XWikiContext context) throws SpaceManagerException { Space space = getSpace(spaceName, context); if (deleteData) { if (getSpaceManagerExtension().preDeleteSpace(space.getSpaceName(), true, context)) { // search for all documents in the space String hql = "where doc.web = '" + space.getSpaceName() + "'"; try { List spaceDocs = context.getWiki().getStore().searchDocuments(hql, context); for (Iterator it = spaceDocs.iterator(); it.hasNext();) { XWikiDocument toBeDeleted = (XWikiDocument) it.next(); context.getWiki().deleteDocument(toBeDeleted, context); } getSpaceManagerExtension().postDeleteSpace(space.getSpaceName(), true, context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } } else { // execute pre delete actions if (getSpaceManagerExtension().preDeleteSpace(space.getSpaceName(), deleteData, context)) { if (!space.isNew()) { space.setType("deleted"); try { space.saveWithProgrammingRights(); // execute post delete actions getSpaceManagerExtension().postDeleteSpace(space.getSpaceName(), deleteData, context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } } } } /** * {@inheritDoc} */ public void deleteSpace(String spaceName, XWikiContext context) throws SpaceManagerException { deleteSpace(spaceName, false, context); } /** * {@inheritDoc} */ public void undeleteSpace(String spaceName, XWikiContext context) throws SpaceManagerException { Space space = getSpace(spaceName, context); if (space.isDeleted()) { space.setType(getSpaceTypeName()); try { space.saveWithProgrammingRights(); } catch (XWikiException e) { throw new SpaceManagerException(e); } } } /** * {@inheritDoc} */ public Space getSpace(String spaceName, XWikiContext context) throws SpaceManagerException { // Init the space object but do not create anything if it does not exist return newSpace(spaceName, spaceName, false, context); } /** * {@inheritDoc} */ public List getSpaces(int nb, int start, XWikiContext context) throws SpaceManagerException { List spaceNames = getSpaceNames(nb, start, context); return getSpaceObjects(spaceNames, context); } public List getSpaces(int nb, int start, String ordersql, XWikiContext context) throws SpaceManagerException { List spaceNames = getSpaceNames(nb, start, ordersql, context); return getSpaceObjects(spaceNames, context); } /** * Returns a list of nb space names starting at start * * @param context The XWiki Context * @return list of Space objects * @throws SpaceManagerException */ protected List getSpaceObjects(List spaceNames, XWikiContext context) throws SpaceManagerException { if (spaceNames == null) return null; List spaceList = new ArrayList(); for (int i = 0; i < spaceNames.size(); i++) { String spaceName = (String) spaceNames.get(i); Space space = getSpace(spaceName, context); spaceList.add(space); } return spaceList; } public List getSpaceNames(int nb, int start, XWikiContext context) throws SpaceManagerException { return getSpaceNames(nb, start, "", context); } /** * {@inheritDoc} */ public List getSpaceNames(int nb, int start, String ordersql, XWikiContext context) throws SpaceManagerException { String type = getSpaceTypeName(); String className = getSpaceClassName(); String sql; if (hasCustomMapping()) sql = "select distinct doc.web from XWikiDocument as doc, BaseObject as obj, " + className + " as space where doc.fullName = obj.name and obj.className='" + className + "' and obj.id = space.id and space.type='" + type + "'" + ordersql; else sql = "select distinct doc.web from XWikiDocument as doc, BaseObject as obj, StringProperty typeprop where doc.fullName=obj.name and obj.className = '" + className + "' and obj.id=typeprop.id.id and typeprop.id.name='type' and typeprop.value='" + type + "'" + ordersql; List spaceList = null; try { spaceList = context.getWiki().getStore().search(sql, nb, start, context); } catch (XWikiException e) { throw new SpaceManagerException(e); } return spaceList; } /** * Performs a search for spaces * * @param fromsql The sql fragment describing the source of the search * @param wheresql The sql fragment describing the where clause of the search * @param ordersql The sql fragment describing the order in wich the spaces should be returned * @param nb The number of spaces to return (limit) * @param start Number of spaces to skip * @param context XWiki context * @return A list with space objects matching the search * @throws SpaceManagerException */ public List searchSpaces(String fromsql, String wheresql, String ordersql, int nb, int start, XWikiContext context) throws SpaceManagerException { List spaceNames = searchSpaceNames(fromsql, wheresql, ordersql, nb, start, context); return getSpaceObjects(spaceNames, context); } /** * Performs a search for spaces. This variant returns the spaces ordered ascending by creation * date * * @param fromsql The sql fragment describing the source of the search * @param wheresql The sql fragment describing the where clause of the search * @param nb The number of spaces to return (limit) * @param start Number of spaces to skip * @param context XWiki context * @return A list with space objects matching the search * @throws SpaceManagerException */ public List searchSpaces(String fromsql, String wheresql, int nb, int start, XWikiContext context) throws SpaceManagerException { return searchSpaces(fromsql, wheresql, "", nb, start, context); } /** * Performs a search for space names * * @param fromsql The sql fragment describing the source of the search * @param wheresql The sql fragment describing the where clause of the search * @param ordersql The sql fragment describing the order in wich the spaces should be returned * @param nb The number of spaces to return (limit) * @param start Number of spaces to skip * @param context XWiki context * @return A list of strings representing the names of the spaces matching the search * @throws SpaceManagerException */ public List searchSpaceNames(String fromsql, String wheresql, String ordersql, int nb, int start, XWikiContext context) throws SpaceManagerException { String type = getSpaceTypeName(); String className = getSpaceClassName(); String sql; if (hasCustomMapping()) sql = "select distinct doc.web from XWikiDocument as doc, BaseObject as obj, " + className + " as space" + fromsql + " where doc.fullName = obj.name and obj.className='" + className + "' and obj.id = space.id and space.type='" + type + "'" + wheresql + ordersql; else sql = "select distinct doc.web from XWikiDocument as doc, BaseObject as obj, StringProperty as typeprop" + fromsql + " where doc.fullName=obj.name and obj.className = '" + className + "' and obj.id=typeprop.id.id and typeprop.id.name='type' and typeprop.value='" + type + "'" + wheresql + ordersql; List spaceList = null; try { spaceList = context.getWiki().getStore().search(sql, nb, start, context); } catch (XWikiException e) { throw new SpaceManagerException(e); } return spaceList; } /** * Performs a search for space names. This variant returns the spaces ordered ascending by * creation date * * @param fromsql The sql fragment describing the source of the search * @param wheresql The sql fragment describing the where clause of the search * @param nb The number of spaces to return (limit) * @param start Number of spaces to skip * @param context XWiki context * @return A list of strings representing the names of the spaces matching the search * @throws SpaceManagerException */ public List searchSpaceNames(String fromsql, String wheresql, int nb, int start, XWikiContext context) throws SpaceManagerException { return searchSpaceNames(fromsql, wheresql, "", nb, start, context); } /** * {@inheritDoc} */ public List getSpaces(String userName, String role, XWikiContext context) throws SpaceManagerException { List spaceNames = getSpaceNames(userName, role, context); return getSpaceObjects(spaceNames, context); } /** * {@inheritDoc} */ public List getSpaceNames(String userName, String role, XWikiContext context) throws SpaceManagerException { String sql; if (role == null) sql = "select distinct doc.web from XWikiDocument as doc, BaseObject as obj, StringProperty as memberprop where doc.name='MemberGroup' and doc.fullName=obj.name and obj.className = 'XWiki.XWikiGroups'" + " and obj.id=memberprop.id.id and memberprop.id.name='member' and memberprop.value='" + userName + "'"; else { String roleGroupName = getRoleGroupName("", role).substring(1); sql = "select distinct doc.web from XWikiDocument as doc, BaseObject as obj, StringProperty as memberprop where doc.name='" + roleGroupName + "' and doc.fullName=obj.name and obj.className = 'XWiki.XWikiGroups'" + " and obj.id=memberprop.id.id and memberprop.id.name='member' and memberprop.value='" + userName + "'"; } List spaceList = null; try { spaceList = context.getWiki().getStore().search(sql, 0, 0, context); } catch (XWikiException e) { throw new SpaceManagerException(e); } return spaceList; } /** * {@inheritDoc} */ public boolean updateSpaceFromRequest(Space space, XWikiContext context) throws SpaceManagerException { space.updateSpaceFromRequest(); if (space.validateSpaceData()) return true; else return false; } /** * {@inheritDoc} */ public boolean validateSpaceData(Space space, XWikiContext context) throws SpaceManagerException { return space.validateSpaceData(); } /** * {@inheritDoc} */ public void saveSpace(Space space, XWikiContext context) throws SpaceManagerException { try { space.saveWithProgrammingRights(); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public void addAdmin(String spaceName, String username, XWikiContext context) throws SpaceManagerException { try { addUserToGroup(username, getAdminGroupName(spaceName), context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public void addAdmins(String spaceName, List usernames, XWikiContext context) throws SpaceManagerException { for (int i = 0; i < usernames.size(); i++) { addAdmin(spaceName, (String) usernames.get(i), context); } } /** * {@inheritDoc} */ public Collection getAdmins(String spaceName, XWikiContext context) throws SpaceManagerException { try { return getGroupService(context).getAllMembersNamesForGroup( getAdminGroupName(spaceName), 0, 0, context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} * * @see SpaceManager#removeAdmin(String, String, XWikiContext) */ public void removeAdmin(String spaceName, String userName, XWikiContext context) throws SpaceManagerException { try { removeUserFromGroup(userName, getAdminGroupName(spaceName), context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public boolean isAdmin(String spaceName, String userName, XWikiContext context) throws SpaceManagerException { try { return isMemberOfGroup(userName, getAdminGroupName(spaceName), context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public void addUserToRole(String spaceName, String username, String role, XWikiContext context) throws SpaceManagerException { try { addUserToGroup(username, getRoleGroupName(spaceName, role), context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public void addUsersToRole(String spaceName, List usernames, String role, XWikiContext context) throws SpaceManagerException { for (int i = 0; i < usernames.size(); i++) { addUserToRole(spaceName, (String) usernames.get(i), role, context); } } /** * {@inheritDoc} */ public Collection getUsersForRole(String spaceName, String role, XWikiContext context) throws SpaceManagerException { try { return sortUserNames(getGroupService(context).getAllMembersNamesForGroup( getRoleGroupName(spaceName, role), 0, 0, context), context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public boolean isMember(String spaceName, String username, XWikiContext context) throws SpaceManagerException { try { return isMemberOfGroup(username, getMemberGroupName(spaceName), context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public void addUserToRoles(String spaceName, String username, List roles, XWikiContext context) throws SpaceManagerException { for (int i = 0; i < roles.size(); i++) { addUserToRole(spaceName, username, (String) roles.get(i), context); } } /** * {@inheritDoc} */ public void addUsersToRoles(String spaceName, List usernames, List roles, XWikiContext context) throws SpaceManagerException { for (int i = 0; i < usernames.size(); i++) { addUserToRoles(spaceName, (String) usernames.get(i), roles, context); } } /** * {@inheritDoc} * * @see SpaceManager#removeUserFromRoles(String, String, List, XWikiContext) */ public void removeUserFromRoles(String spaceName, String userName, List roles, XWikiContext context) throws SpaceManagerException { for (int i = 0; i < roles.size(); i++) { removeUserFromRole(spaceName, userName, (String) roles.get(i), context); } } /** * {@inheritDoc} */ public void removeUserFromRole(String spaceName, String userName, String role, XWikiContext context) throws SpaceManagerException { try { removeUserFromGroup(userName, getRoleGroupName(spaceName, role), context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public void addMember(String spaceName, String username, XWikiContext context) throws SpaceManagerException { try { addUserToGroup(username, getMemberGroupName(spaceName), context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} * * @see SpaceManager#removeMember(String, String, XWikiContext) */ public void removeMember(String spaceName, String userName, XWikiContext context) throws SpaceManagerException { try { // remove admin role if (isAdmin(spaceName, userName, context)) { removeAdmin(spaceName, userName, context); } // remove all the other roles Iterator it = getRoles(spaceName, context).iterator(); while (it.hasNext()) { String role = (String) it.next(); removeUserFromRole(spaceName, userName, role, context); } // delete space user profile deleteSpaceUserProfile(spaceName, userName, context); // remove member removeUserFromGroup(userName, getMemberGroupName(spaceName), context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } protected boolean isMemberOfGroup(String username, String groupname, XWikiContext context) throws XWikiException { Collection coll = context.getWiki().getGroupService(context).getAllGroupsNamesForMember(username, 0, 0, context); Iterator it = coll.iterator(); while (it.hasNext()) { if (groupname.equals((String) it.next())) return true; } return false; } /** * High speed user adding without resaving the whole groups doc * * @param username * @param groupName * @param context * @throws XWikiException */ protected void addUserToGroup(String username, String groupName, XWikiContext context) throws XWikiException { // don't add if he is already a member if (isMemberOfGroup(username, groupName, context)) return; XWiki xwiki = context.getWiki(); BaseClass groupClass = xwiki.getGroupClass(context); XWikiDocument groupDoc = xwiki.getDocument(groupName, context); BaseObject memberObject = (BaseObject) groupClass.newObject(context); memberObject.setClassName(groupClass.getName()); memberObject.setName(groupDoc.getFullName()); memberObject.setStringValue("member", username); groupDoc.addObject(groupClass.getName(), memberObject); String content = groupDoc.getContent(); if ((content == null) || (content.equals(""))) groupDoc.setContent("#includeForm(\"XWiki.XWikiGroupSheet\")"); xwiki.saveDocument(groupDoc, context.getMessageTool() .get("core.comment.addedUserToGroup"), context); } private void removeUserFromGroup(String userName, String groupName, XWikiContext context) throws XWikiException { // don't remove if he's not a member if (!isMemberOfGroup(userName, groupName, context)) { return; } XWiki xwiki = context.getWiki(); BaseClass groupClass = xwiki.getGroupClass(context); XWikiDocument groupDoc = xwiki.getDocument(groupName, context); BaseObject memberObject = groupDoc.getObject(groupClass.getName(), "member", userName); if (memberObject == null) { return; } groupDoc.removeObject(memberObject); xwiki.saveDocument(groupDoc, context.getMessageTool().get( "core.comment.removedUserFromGroup"), context); } /** * {@inheritDoc} */ public void addMembers(String spaceName, List usernames, XWikiContext context) throws SpaceManagerException { for (int i = 0; i < usernames.size(); i++) { addMember(spaceName, (String) usernames.get(i), context); } } /** * {@inheritDoc} * * @see SpaceManager#getMembers(String, XWikiContext) */ public Collection getMembers(String spaceName, XWikiContext context) throws SpaceManagerException { try { return sortUserNames(getGroupService(context).getAllMembersNamesForGroup( getMemberGroupName(spaceName), 0, 0, context), context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } private List sortUserNames(Collection collectionOfUsers, final XWikiContext context) { List users = new ArrayList(collectionOfUsers); Collections.sort(users, new Comparator() { public int compare(Object a, Object b) { try { XWikiDocument aDoc = context.getWiki().getDocument((String) a, context); XWikiDocument bDoc = context.getWiki().getDocument((String) b, context); String aFirstName = aDoc.getObject("XWiki.XWikiUsers").getStringValue("first_name"); String bFirstName = bDoc.getObject("XWiki.XWikiUsers").getStringValue("first_name"); int cmp = aFirstName.compareToIgnoreCase(bFirstName); if (cmp == 0) { String aLastName = aDoc.getObject("XWiki.XWikiUsers").getStringValue("last_name"); String bLastName = bDoc.getObject("XWiki.XWikiUsers").getStringValue("last_name"); return aLastName.compareTo(bLastName); } else { return cmp; } } catch (Exception e) { return ((String) a).compareTo((String) b); } } }); return users; } public String getMemberGroupName(String spaceName) { return getSpaceManagerExtension().getMemberGroupName(spaceName); } public String getAdminGroupName(String spaceName) { return getSpaceManagerExtension().getAdminGroupName(spaceName); } public String getRoleGroupName(String spaceName, String role) { return getSpaceManagerExtension().getRoleGroupName(spaceName, role); } protected XWikiGroupService getGroupService(XWikiContext context) throws XWikiException { return context.getWiki().getGroupService(context); } public SpaceUserProfile getSpaceUserProfile(String spaceName, String username, XWikiContext context) throws SpaceManagerException { return newUserSpaceProfile(username, spaceName, context); } private void deleteSpaceUserProfile(String spaceName, String userName, XWikiContext context) throws SpaceManagerException { try { String docName = getSpaceUserProfilePageName(userName, spaceName); XWikiDocument doc = context.getWiki().getDocument(docName, context); if (!doc.isNew()) context.getWiki().deleteDocument(doc, context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } public String getSpaceUserProfilePageName(String userName, String spaceName) { return getSpaceManagerExtension().getSpaceUserProfilePageName(userName, spaceName); } protected SpaceUserProfile newUserSpaceProfile(String user, String space, XWikiContext context) throws SpaceManagerException { try { return new SpaceUserProfileImpl(user, space, this, context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public List getLastModifiedDocuments(String spaceName, XWikiContext context, boolean recursive, int nb, int start) throws SpaceManagerException { notImplemented(); return null; } /** * {@inheritDoc} */ public Collection getRoles(String spaceName, XWikiContext context) throws SpaceManagerException { // The roles notion is not natively implemented in the spacemanager plugin yet, // so we return a empty list. Plugins that extend the spacemanager plugin can overload this // method to implement roles, either by hardcoding or retrieving from DB the roles list. // @TODO Implement methods to set a list of roles for a space. return Collections.EMPTY_LIST; } /** * {@inheritDoc} * * @see SpaceManager#getRoles(String, String, XWikiContext) */ public Collection getRoles(String spaceName, String memberName, XWikiContext context) throws SpaceManagerException { try { Collection memberRoles = context.getWiki().getGroupService(context).getAllGroupsNamesForMember(memberName, 0, 0, context); Collection spaceRoles = getRoles(spaceName, context); memberRoles.retainAll(spaceRoles); return memberRoles; } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public List getLastModifiedDocuments(String spaceName, XWikiContext context) throws SpaceManagerException { notImplemented(); return null; } /** * {@inheritDoc} */ public List searchDocuments(String spaceName, String hql, XWikiContext context) throws SpaceManagerException { notImplemented(); return null; } /** * {@inheritDoc} */ public int countSpaces(XWikiContext context) throws SpaceManagerException { String type = getSpaceTypeName(); String className = getSpaceClassName(); String sql; if (hasCustomMapping()) sql = "select count(*) from XWikiDocument as doc, BaseObject as obj, " + className + " as space" + " where doc.fullName = obj.name and obj.className='" + className + "' and obj.id = space.id and space.type='" + type + "'"; else sql = "select count(*) from XWikiDocument as doc, BaseObject as obj, StringProperty as typeprop" + " where doc.fullName=obj.name and obj.className = '" + className + "' and obj.id=typeprop.id.id and typeprop.id.name='type' and typeprop.value='" + type + "'"; try { List result = context.getWiki().search(sql, context); Integer res = (Integer) result.get(0); return res.intValue(); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} * * @see SpaceManager#joinSpace(String, XWikiContext) */ public boolean joinSpace(String spaceName, XWikiContext context) throws SpaceManagerException { try { SpaceUserProfile userProfile = newUserSpaceProfile(context.getUser(), spaceName, context); userProfile.updateProfileFromRequest(); userProfile.saveWithProgrammingRights(); addMember(spaceName, context.getUser(), context); sendMail(SpaceAction.JOIN, getSpace(spaceName, context), context); return true; } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * Helper function to send email after a space action. This mail template full name is composed * of the space name and the action with the following convention : spaceName + "." + * "MailTemplate" + action + "Space", as in MySpace.MailTemplateJoinSpace * * @see getTemplateMailPageName * @param action the action which triggered the mail sending. See * {@link SpaceManager.SpaceAction} for possible actions. * @param space The space on which the action has triggered the mail sending * @throws SpaceManagerException */ private void sendMail(String action, Space space, XWikiContext context) throws SpaceManagerException { if (!mailNotification) { return; } VelocityContext vContext = new VelocityContext(); vContext.put("space", space); String fromUser = context.getWiki().getXWikiPreference("space_email", context); if (fromUser == null || fromUser.trim().length() == 0) { fromUser = context.getWiki().getXWikiPreference("admin_email", context); } String[] toUsers = new String[0]; if (SpaceAction.CREATE.equals(action)) { // notify space administrators upon space creation Collection admins = getAdmins(space.getSpaceName(), context); toUsers = (String[]) admins.toArray(new String[admins.size()]); } else if (SpaceAction.JOIN.equals(action)) { // send join group confirmation e-mail boolean optOutEmail = false; try { optOutEmail = context.getWiki().getUserPreferenceAsInt("opt_out", context) != 0; } catch(NumberFormatException e) { // if nothing is specified then we don't opt out } if (optOutEmail) { return; } else { toUsers = new String[] {context.getUser()}; } } if (fromUser == null) { throw new SpaceManagerException(SpaceManagerException.MODULE_PLUGIN_SPACEMANAGER, SpaceManagerException.ERROR_SPACE_SENDER_EMAIL_INVALID, "Sender email is invalid"); } boolean toUsersValid = toUsers.length > 0; for (int i = 0; i < toUsers.length && toUsersValid; i++) { if (!isEmailAddress(toUsers[i])) { toUsers[i] = getEmailAddress(toUsers[i], context); } if (toUsers[i] == null) { toUsersValid = false; } } if (!toUsersValid) { throw new SpaceManagerException(SpaceManagerException.MODULE_PLUGIN_SPACEMANAGER, SpaceManagerException.ERROR_SPACE_TARGET_EMAIL_INVALID, "Target email is invalid"); } String strToUsers = join(toUsers, ","); MailSenderPlugin mailSender = getMailSenderPlugin(context); try { String templateDocFullName = getTemplateMailPageName(space.getSpaceName(), action, context); XWikiDocument mailDoc = context.getWiki().getDocument(templateDocFullName, context); XWikiDocument translatedMailDoc = mailDoc.getTranslatedDocument(context); mailSender.prepareVelocityContext(fromUser, strToUsers, null, null, vContext, context); vContext.put("xwiki", new com.xpn.xwiki.api.XWiki(context.getWiki(), context)); vContext.put("context", new com.xpn.xwiki.api.Context(context)); String mailSubject = XWikiVelocityRenderer.evaluate(translatedMailDoc.getTitle(), templateDocFullName, vContext, context); String mailContent = XWikiVelocityRenderer.evaluate(translatedMailDoc.getContent(), templateDocFullName, vContext, context); Mail mail = new Mail(fromUser, strToUsers, null, null, mailSubject, mailContent, null); mailSender.sendMail(mail, context); } catch (Exception e) { throw new SpaceManagerException(SpaceManagerException.MODULE_PLUGIN_SPACEMANAGER, SpaceManagerException.ERROR_SPACE_SENDING_EMAIL_FAILED, "Sending notification email failed", e); } } private MailSenderPlugin getMailSenderPlugin(XWikiContext context) throws SpaceManagerException { MailSenderPlugin mailSender = (MailSenderPlugin) context.getWiki().getPlugin("mailsender", context); if (mailSender == null) throw new SpaceManagerException(SpaceManagerException.MODULE_PLUGIN_SPACEMANAGER, SpaceManagerException.ERROR_SPACE_MANAGER_REQUIRES_MAILSENDER_PLUGIN, "SpaceManager requires the mail sender plugin"); return mailSender; } // code duplicated from InvitationManagerImpl !!! private static final String join(String[] array, String separator) { StringBuffer result = new StringBuffer(""); if (array.length > 0) { result.append(array[0]); } for (int i = 1; i < array.length; i++) { result.append("," + array[i]); } return result.toString(); } // code duplicated from InvitationManagerImpl !!! private boolean isEmailAddress(String str) { return str.contains("@"); } // code duplicated from InvitationManagerImpl !!! private String getEmailAddress(String user, XWikiContext context) throws SpaceManagerException { try { String wikiuser = (user.startsWith("XWiki.")) ? user : "XWiki." + user; if (wikiuser == null) return null; XWikiDocument userDoc = null; userDoc = context.getWiki().getDocument(wikiuser, context); if (userDoc.isNew()) return null; String email = ""; try { email = userDoc.getObject("XWiki.XWikiUsers").getStringValue("email"); } catch (Exception e) { return null; } if ((email == null) || (email.equals(""))) return null; return email; } catch (Exception e) { throw new SpaceManagerException(SpaceManagerException.MODULE_PLUGIN_SPACEMANAGER, SpaceManagerException.ERROR_SPACE_CANNOT_FIND_EMAIL_ADDRESS, "Cannot find email address of user " + user, e); } } /** * Convention based private helper to retrieve a mail template full name from a space name and * an action name. TODO I think we should have the possibility to select for each action a * template that is not located in the space itself, but in another web of the wiki. This would * be to avoid copying this template each time we create a space if its content is not supposed * to be modified, And thus reduce the impact of space creation on the db size. */ private String getTemplateMailPageName(String spaceName, String action, XWikiContext context) { String docName = spaceName + "." + "MailTemplate" + action + "Space"; try { if (context.getWiki().getDocument(docName, context).isNew()) { docName = null; } } catch (XWikiException e) { docName = null; } if (docName == null) { docName = getDefaultResourceSpace(context) + "." + "MailTemplate" + action + "Space"; } return docName; } private String getDefaultResourceSpace(XWikiContext context) { return context.getWiki().Param("xwiki.spacemanager.resourcespace", SpaceManager.DEFAULT_RESOURCE_SPACE); } public boolean isMailNotification() { return mailNotification; } public void setMailNotification(boolean mailNotification) { this.mailNotification = mailNotification; } }