/*
ESUP-portail is a french academic project developed under the GPL (General Public License) augmented according to the following :
A binary or source file developped by ESUP-portail can be used or compiled with products under Apache license.
The official english text of the GPL can be found here : http://www.gnu.org/licenses/gpl.html .
A non official french translation can be found here : http://www.linux-France.org/article/these/gpl.html .
The different kinds of licenses governing the products developed by the Apache foundation can be found here : http://www.apache.org/licenses .
It follows that you can as well as use download contents as well modify and redistribute them provided you respect the GPL terms.
Downloading and using such contents do not provide any guaranty.
Be sure that you have well understood the terms of the license before using the contents it covers.
The ESUP-portail distribution includes the following distributions :
    * UPortal : 
      software developed by JA-SIG (Java Architecture - Special Interest Group)
      You can find the license page here : http://mis105.udel.edu/ja-sig/uportal/license.html
    * CAS :
      SSO solution developed by Yale University
      You can find the project page here : http://www.yale.edu/tp/auth
    * Cocoon :
      XML framework distributed by the Apache foundation under Apache license;
      Please find the full text here : http://cocoon.apache.org/2.1/license.html
    * Mod_dav:
      A DAV module for Apache web server
      You can find the project page here : http://www.webdav.org/mod_dav
    * IMP :
      webmail from Horde application framework
      You can find the project page here : http://www.horde.org
    * …. To be completed
*/
 
package org.esupportail.portal.channels.CStockage;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.esupportail.portal.channels.CAnnuaire.CAnnuaireServantFactory;
import org.esupportail.portal.channels.CStockage.administration.AdministrationTool;
import org.esupportail.portal.channels.CStockage.administration.Attribute;
import org.esupportail.portal.channels.CStockage.administration.Constants;
import org.esupportail.portal.channels.CStockage.config.ChannelConfiguration;
import org.esupportail.portal.channels.CStockage.config.Server;
import org.esupportail.portal.channels.CStockage.config.Space;
import org.esupportail.portal.channels.CStockage.exception.CancelException;
import org.esupportail.portal.channels.CStockage.exception.ChannelException;
import org.esupportail.portal.channels.CStockage.exception.DataBaseException;
import org.esupportail.portal.channels.CStockage.exception.PropertiesException;
import org.esupportail.portal.channels.CStockage.exception.ServerException;
import org.esupportail.portal.channels.CStockage.exception.StillExistsServerException;
import org.esupportail.portal.channels.CStockage.spacesPersonalization.DirectorySharingProperties;
import org.esupportail.portal.channels.CStockage.spacesPersonalization.target.GroupForPersonalization;
import org.esupportail.portal.channels.CStockage.spacesPersonalization.target.UserForPersonalization;
import org.jasig.portal.ChannelCacheKey;
import org.jasig.portal.ChannelRuntimeData;
import org.jasig.portal.ChannelStaticData;
import org.jasig.portal.ICacheable;
import org.jasig.portal.IServant;
import org.jasig.portal.PortalException;
import org.jasig.portal.channels.BaseChannel;
import org.jasig.portal.channels.groupsmanager.CGroupsManagerServantFactory;
import org.jasig.portal.groups.EntityGroupImpl;
import org.jasig.portal.security.IPerson;
import org.jasig.portal.services.GroupService;
import org.jasig.portal.utils.XSLT;
import org.xml.sax.ContentHandler;

/**
 * Id: CStockageAdministration.java,v 1.0 2 mai 2005<br/>
 * Copyright (c) 2004 Esup Portail (www.esup-portail.org)<br/>
 * Classes: CStockageAdministration<br/>
 * Original Author: Yohan Colmant<br/>
 * Channel used to manage personal files on a webdav server through the portal<br/>
 */




public class CStockageAdministration extends BaseChannel implements ICacheable {


	/**
	 * Logger object
	 */
	protected static final Log log = LogFactory.getLog(CStockageAdministration.class);
	
	
	
	
	private ChannelStaticData staticData;

	
	
	/**
	 * Error at the beginning of the channel
	 */
	private ChannelException setStaticDataException;		
	
	/**
	 * The stylesheet used for the transformation
	 */
	private StringBuffer stylesheet;

	/**
	 * User login
	 */
	private String portalLogin;
	
	/**
	 * The tool used to manage the administration of the servers
	 */
	private AdministrationTool adminTool;
	
	
	
	


	/**
	 * The servant channel used for groups and users selection
	 */
	private IServant slave;
	
	
	
	
	/**
	 * Constructor
	 */
	public CStockageAdministration() {				
		
	}	

	
	/**
	 * Receive static channel data from the portal. Satisfies implementation of IChannel Interface.
	 * 
	 * @param sd <b>ChannelStaticData</b> static channel data
	 */
	public void setStaticData(ChannelStaticData sd) {
		this.staticData = sd;			
		
		try {
			// the uportal person object
			IPerson person = sd.getPerson();			
		
			// the usernameAttribute
			String userNameAttribute = ChannelConfiguration.getInstance().getUsernameAttribute();
		
			// Set the user login			
			portalLogin = (String)person.getAttribute(userNameAttribute);
			
			// set the object used to administrate the servers
			adminTool = new AdministrationTool();
			
			// init the value of directories for servant
			staticData.setParameter("serverView", ChannelConfiguration.getInstance().getDirectoriesList());
			
		}
		catch(PropertiesException e) {
			this.setStaticDataException = e;
		}
		
	}
	
	
	
	
		
	
	/**
	 * Output channel content to the portal
	 * 
	 * @param out a sax document handler
	 */
	public void renderXML(ContentHandler out) throws PortalException {

		
		// Create a new XSLT styling engine		
		XSLT xslt = new XSLT(this);
		
		
		// Manage the actions
		String currentMode = runtimeData.getParameter("administrationMode");
		StringBuffer xml = null;
		
		// init the default mode
		if (currentMode== null) {
			currentMode = Constants.DEFAULT_MODE;
		}

		// log
		if (log.isDebugEnabled()){
			log.debug("checkCalledAction"+" :: currentMode = "+currentMode);
		}	
		
		// check if servant is active or not
		if (slave!=null) {
			slave.setRuntimeData(runtimeData);
			if (!slave.isFinished()) {								
				slave.renderXML(out);
				return;
			}
			else {								
				currentMode = Constants.VALID_SERVANT_RESULTS;
			}
		}
		
		//////////////////////////////////////////////////////
		// C H E C K   M O D E
		try {
			
			if (setStaticDataException!=null)
				throw setStaticDataException;
			
			
			//////////////////////////////////////////////////////
			// S E R V E R S
			
			// default mode
			if (currentMode.equals(Constants.DEFAULT_MODE)) {
				stylesheet = new StringBuffer("CStockageAdministration");
				xml = renderXmlDefault(runtimeData, null);
			}
		
			// set the name of the new server
			else if (currentMode.equals(Constants.SET_NEW_SERVER_NAME_MODE)){
				stylesheet = new StringBuffer("setNewServerName");
				xml = new StringBuffer();
			}

			// after setting the name of the new server
			else if (currentMode.equals(Constants.NEW_SERVER_MODE)){
				stylesheet = new StringBuffer("server");
				xml = renderXmlNewServer(runtimeData, out);
			}

			//////////////////////////////////////////////////////
			// S E R V E R
		
			// default server mode
			else if (currentMode.equals(Constants.DEFAULT_SERVER_MODE)){
				stylesheet = new StringBuffer("server");
				xml = renderXmlDefaultServer(runtimeData, out);
			}

			// confirm delete
			else if (currentMode.equals(Constants.CONFIRM_DELETE_SERVER_MODE)) {		
				stylesheet = new StringBuffer("confirmDeleteServer");
				xml = renderXmlConfirmDeleteServer(runtimeData);				
			}

			// delete
			else if (currentMode.equals(Constants.DELETE_SERVER_MODE)) {		
				deleteServer(runtimeData);
				stylesheet = new StringBuffer("CStockageAdministration");
				xml = renderXmlDefault(runtimeData, null);	
			}

			// confirm rename
			else if (currentMode.equals(Constants.CONFIRM_RENAME_SERVER_MODE)) {		
				stylesheet = new StringBuffer("setRenameServer");
				xml = renderXmlConfirmRenameServer(runtimeData);				
			}

			// rename
			else if (currentMode.equals(Constants.RENAME_SERVER_MODE)) {		
				renameServer(runtimeData);
				stylesheet = new StringBuffer("CStockageAdministration");
				xml = renderXmlDefault(runtimeData, null);	
			}

			//////////////////////////////////////////////////////
			// S P A C E
		
			// default space mode
			else if (currentMode.equals(Constants.DEFAULT_SPACE_MODE)){
				stylesheet = new StringBuffer("space");
				xml = renderXmlDefaultSpace(runtimeData, out);
			}
			
			// valid the servant results
			else if (currentMode.equals(Constants.VALID_SERVANT_RESULTS)) {		
				stylesheet = new StringBuffer("space");
				xml = renderXmlValidServantResults(runtimeData, staticData, out);				
			}
			
			// confirm delete
			/*else if (currentMode.equals(Constants.CONFIRM_DELETE_SPACE_MODE)) {		
				stylesheet = new StringBuffer("confirmDeleteSpace");
				xml = renderXmlConfirmDeleteSpace(runtimeData);				
			}*/

			// delete
			else if (currentMode.equals(Constants.DELETE_SPACE_MODE)) {		
				deleteSpace(runtimeData);
				stylesheet = new StringBuffer("server");
				xml = renderXmlDefaultServer(runtimeData, out);	
			}
			
		}
		
		catch(ChannelException e) {
			stylesheet = new StringBuffer("CStockageAdministration");
			// log
			if (log.isDebugEnabled()){
				log.debug("renderXML"+" :: "+e);
			}
			
			try {
				xml = renderXmlDefault(runtimeData, e);
			}
			catch(ChannelException ex) {
				// log
				if (log.isDebugEnabled()){
					log.debug("renderXML"+" :: "+e);
				}
				xml = renderXmlChannelException(e);
			}
			
		}
		
		
		// do the render
		if (xml != null) {
			xsltTransformation(xslt, xml, out, runtimeData, stylesheet);
		}
		
	}
	
	
	
	
	
	/**
	 * Do the XSLT transformation in the channel
	 * @param xslt the XSLT object
	 * @param xmlTemp the XML generated
	 * @param out the ContentHandler object
	 * @param runtimeData the ChannelRuntimeData object
	 * @param stylesheet the stylesheet used
	 * @throws PortalException
	 */
	public static void xsltTransformation(XSLT xslt, StringBuffer xmlTemp, ContentHandler out, ChannelRuntimeData runtimeData, StringBuffer stylesheet) throws PortalException {
		
		StringBuffer xml = new StringBuffer();
		xml.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");			
		xml.append("<ROOT>");
		xml.append(xmlTemp);
		
		// the baseActionUrl
		String baseActionUrl = runtimeData.getBaseActionURL();
		
		// set the stylesheet and the parameters
		
		//specify the stylesheet selector		
		xslt.setXSL("CStockage.ssl", stylesheet.toString(), runtimeData.getBrowserInfo());		
		
		//url to the channel
		xslt.setStylesheetParameter("baseActionURL",baseActionUrl);				
		
		// the final balise
		xml.append("</ROOT>");

		//System.out.println(xml+"\n\n");
		
		//pass the result XML to the styling engine.
		String s = xml.toString();		
		xslt.setXML(s);		

		// set the output Handler for the output.
		xslt.setTarget(out);
	
		// do the deed
		xslt.transform();	
	}
	


	/**
	 * Return the xml when we have to show a information message
	 * @param informationCode the code for the information message
	 * @return the xml when we have to show a information message
	 */
	public StringBuffer renderXmlWithInformation(String informationCode) throws PropertiesException {
		stylesheet = new StringBuffer("CStockageAdministration");
		StringBuffer xml = new StringBuffer();
		
		if (informationCode!=null)
			xml.append("<INFORMATION>"+informationCode+"</INFORMATION>");
		
		return xml;
	}
	
	
	
	
	/**
	 * Return the xml when we have a ChannelException exception
	 * @param e the throwed exception
	 * @return the xml when we have a ChannelException exception
	 */
	public StringBuffer renderXmlChannelException(ChannelException e) {
		stylesheet = new StringBuffer("CStockageAdministration");
		StringBuffer xml = new StringBuffer();
		
		xml.append("<ERRORS>");
		if ( e!=null )
			xml.append("<ERROR channelCode=\""+e.getErrorCode()+"\" />");
		
		xml.append("</ERRORS>");
		return xml;
	}
	
		

	
		
	/**************************
	 *  Administration servers
	 **************************/
	
	
	/**
	 * The list of the servers
	 */
	private Vector servers;
	
	/**
	 * The server we are editing
	 */
	private Server currentServer;
	
	/**
	 * The server we are editing
	 */
	private Server tempAdminServer;
	
	
	
	
	/**
	 * Load the servers from the database
	 * @throws DataBaseException
	 */
	private void loadServers() throws DataBaseException, PropertiesException, ServerException {
		servers = adminTool.getAdministratedSpaces();//TODO
	}
	
	

	/**
	 * Return the xml for the default mode
	 * @param runtimeData the ChannelRuntimeData object
	 * @param e exception throwed
	 * @return the xml for the default mode
	 */
	public StringBuffer renderXmlDefault(ChannelRuntimeData runtimeData, ChannelException e) throws DataBaseException, PropertiesException, ServerException {
		StringBuffer xml = new StringBuffer();
		
		// if error throwed
		if (e!=null) {
			xml.append(renderXmlChannelException(e));
		}
		
		// load the server's list
		loadServers();
		
		// generate the XML
		xml.append("<servers>\n");
		for (int i=0; i<servers.size(); i++) {
			Server ser = (Server)servers.get(i);
			xml.append("<server name=\""+ser.getName()+"\" index=\""+i+"\"/>\n");
		}
		xml.append("</servers>\n");
		
		return xml;
	}
	


	/**
	 * Return the xml for the new server mode
	 * @param runtimeData the ChannelRuntimeData object
	 * @return the xml for the new server mode
	 * @throws CancelException
	 * @throws StillExistsServerException
	 */
	public StringBuffer renderXmlNewServer(ChannelRuntimeData runtimeData, ContentHandler out) throws CancelException, StillExistsServerException, DataBaseException, PropertiesException, ServerException, PortalException {
		
		// if cancel
		if (runtimeData.getParameter("Cancel")!=null) {
			CancelException e = new CancelException();
			
			// log
			if (log.isDebugEnabled()){
				log.debug("renderXmlNewServer"+" :: "+e);
			}
			
			throw e;
		}
		
		// get the name of the new server
		String name = runtimeData.getParameter("new_server");
		
		// check if this name is still used
		boolean found = false;
		for (int i=0; servers!=null && i<servers.size(); i++) {
			Server s = (Server)servers.elementAt(i);
			if (s.getName().toLowerCase().equals(name.toLowerCase())) {
				found = true;
			}
		}
		if (found) {
			StillExistsServerException e = new StillExistsServerException();
			
			// log
			if (log.isDebugEnabled()){
				log.debug("renderXmlNewServer"+" :: "+e);
			}
			
			throw e;
		}
		
		// redirect to the edition
		return renderXmlDefaultServer(runtimeData, out);
	}
	
	
	
	
	
	
	
	
	

	
	/**************************
	 *  Administration server
	 **************************/

	
	/**
	 * The attributes to set the server
	 */
	private Vector serverAttributes;
	
	
	

	/**
	 * Return the xml for the default spaces mode
	 * @param runtimeData the ChannelRuntimeData object
	 * @return the xml for the default spaces mode
	 * @throws CancelException
	 */
	private StringBuffer renderXmlDefaultServer(ChannelRuntimeData runtimeData, ContentHandler out) throws CancelException, DataBaseException, PropertiesException, ServerException, PortalException {
		
		// if we select a server
		String ind = runtimeData.getParameter("index");
		if (ind!=null) {
			int index = Integer.parseInt(ind);
			currentServer = (Server)servers.elementAt(index);
			tempAdminServer = (Server)currentServer.clone();
		}
		
		// if we set a new server
		String name = runtimeData.getParameter("new_server");
		if (name != null) {
			currentServer = new Server();
			currentServer.setName(name);
			tempAdminServer = (Server)currentServer.clone();
		}

		// check the attributes
		boolean attributesOk = false;
		
		// init the attributes
		if (serverAttributes==null) {
			serverAttributes = getNewServerAttributesList(tempAdminServer);
		}
		else {
			attributesOk = checkServerAttibutes(runtimeData, serverAttributes, tempAdminServer);
		}

		// if we ask a new space, choose a space or delete a space
		String actionSpace = runtimeData.getParameter("action_space");
		if (actionSpace != null && actionSpace.equals("true")) {
			stylesheet = new StringBuffer("space");
			return renderXmlDefaultSpace(runtimeData, out);
		}
		
		
		// get the mode
		String mode = runtimeData.getParameter("mode");
		
		// if valid
		if (mode!=null && mode.equals("valid")) {
			if (!attributesOk) {
				return getDefaultServerXml(runtimeData);
			}
			else {
				validServer(runtimeData);
				serverAttributes = null;
				
				stylesheet = new StringBuffer("CStockageAdministration");
				return renderXmlDefault(runtimeData, null);
			}
		}

		// if cancel
		if (mode!=null && mode.equals("cancel")) {
			serverAttributes = null;
			CancelException e = new CancelException();
			
			// log
			if (log.isDebugEnabled()){
				log.debug("renderXmlDefaultServer"+" :: "+e);
			}
			
			throw e;
		}
		
		return getDefaultServerXml(runtimeData);
	}
	


	/**
	 * Return the xml for the default spaces mode
	 * @param runtimeData the ChannelRuntimeData object
	 * @return the xml for the default spaces mode
	 */
	public StringBuffer getDefaultServerXml(ChannelRuntimeData runtimeData) {
		StringBuffer xml = new StringBuffer();
		
		xml.append("<server name=\""+tempAdminServer.getName()+"\">\n");
		
		xml.append(getServerAttributesXml(serverAttributes));
		xml.append(getServerSpacesXml(tempAdminServer.getSpaces()));
		
		xml.append("</server>\n");
		
		return xml;
	}
	
	
	
	/**
	 * Get the XML for the attributes
	 * @param serverAttributes the list of attributes to set
	 * @return the xml generated
	 */
	private static StringBuffer getServerAttributesXml(Vector serverAttributes) {
		
		StringBuffer xml = new StringBuffer();
		xml.append("<attributes>\n");
		
		if (serverAttributes!=null) {
			
			Enumeration iter = serverAttributes.elements();
			while(iter.hasMoreElements()) {
				
				Attribute att = (Attribute)iter.nextElement();
				if (!att.isInvisible()) {
					
					// if select area
					if (!(att.getAvailableValues()==null || att.getAvailableValues().size()==0) && att.isModifiable()) {
						xml.append("<attribute input=\"select\" name=\""+att.getName()+"\" value=\""+att.getValue()+"\" obliged=\""+att.isObliged()+"\" goodFormat=\""+att.isGoodFormat()+"\" >\n");
						for (int i=0; i<att.getAvailableValues().size(); i++) {
							String val = (String)att.getAvailableValues().elementAt(i);
							xml.append("<choice value=\""+val+"\"/>\n");
						}
						xml.append("</attribute>\n");
					}
					
					// if text area
					else {
						if (att.getValue() == null) {
							xml.append("<attribute input=\"text\" name=\""+att.getName()+"\" value=\""+""+"\" obliged=\""+att.isObliged()+"\" goodFormat=\""+att.isGoodFormat()+"\" modifiable=\""+att.isModifiable()+"\"  />\n");
						}
						else {
							xml.append("<attribute input=\"text\" name=\""+att.getName()+"\" value=\""+att.getValue()+"\" obliged=\""+att.isObliged()+"\" goodFormat=\""+att.isGoodFormat()+"\" modifiable=\""+att.isModifiable()+"\"  />\n");	
						}
					}
					
				}
			}
			
		}
		
		xml.append("</attributes>\n");
		return xml;
	}
	
	
	

	/**
	 * Get the XML for the spaces
	 * @param serverSpaces the list of spaces to set
	 * @return the xml generated
	 */
	private static StringBuffer getServerSpacesXml(ArrayList serverSpaces) {
		
		StringBuffer xml = new StringBuffer();
		xml.append("<spaces>\n");
		
		for (int i=0; serverSpaces!=null && i<serverSpaces.size(); i++) {
			
			Space space = (Space)serverSpaces.get(i);
			xml.append("<space label=\""+space.getLabel()+"\" key=\""+space.getKey()+"\" index=\""+i+"\" />\n");
			
		}
		
		xml.append("</spaces>\n");
		return xml;
	}
	
	
	/**
	 * Valid the server's settings
	 * @param runtimeData
	 */
	private void validServer(ChannelRuntimeData runtimeData) throws DataBaseException {
		
		// add this server to the list if it is not inside
		boolean found = false;
		for (int i=0; i<servers.size(); i++) {
			Server s = (Server)servers.elementAt(i);
			if (s.getName().toLowerCase().equals(tempAdminServer.getName().toLowerCase())) {
				found = true;
			}
		}
		if (!found) {
			servers.add(tempAdminServer);
			
			// log
			if(log.isDebugEnabled()) {
				log.debug("validServer :: new server found");
			}
			
			// add into the database
			adminTool.addStorageAvailableAdministratedSpace(tempAdminServer);
		}
		
		// if still inside the list, we check if there is a changement
		else {

			// for each serverAttribute, we check if one changed
			boolean generateNewXml = false;
			for (int k=0; generateNewXml==false && k<serverAttributes.size(); k++) {
				
				// the attribute
				Attribute a = (Attribute)serverAttributes.elementAt(k);
				String name = a.getName();
				
				// the old value
				Class oldClass = this.currentServer.getClass();
				String oldValue = null;
				
				// the new value
				Class newClass = this.tempAdminServer.getClass();
				String newValue = null;
				
				
				try {
					
					// we use java refexion to find getter for old attribute
				    BeanInfo bi = Introspector.getBeanInfo(oldClass);
				    PropertyDescriptor[] propertyDescriptor = bi.getPropertyDescriptors();
				    for (int i=0; i<propertyDescriptor.length; i++) {
				    	if (propertyDescriptor[i].getName().equals(name)) {
				    		Method methodRead = propertyDescriptor[i].getReadMethod();
				    		try {
				    			oldValue = (String)methodRead.invoke(this.currentServer, new Object[0]);
				    		}
				    		catch (InvocationTargetException e) {
								log.error("validServer"+" :: "+e);			
							}
				    		
				    		// no more nead to scan propertyDescriptor[] --> exit for statement
				    		i = propertyDescriptor.length;
				    	}
				    }
				    
					// we use java refexion to find getter for new attribute
				    bi = Introspector.getBeanInfo(newClass);
				    propertyDescriptor = bi.getPropertyDescriptors();
				    for (int i=0; i<propertyDescriptor.length; i++) {
				    	if (propertyDescriptor[i].getName().equals(name)) {
				    		Method methodRead = propertyDescriptor[i].getReadMethod();
				    		try {
				    			newValue = (String)methodRead.invoke(this.tempAdminServer, new Object[0]);
				    		}
				    		catch (InvocationTargetException e) {
								log.error("validServer"+" :: "+e);			
							}
				    		
				    		// no more nead to scan propertyDescriptor[] --> exit for statement
				    		i = propertyDescriptor.length;
				    	}
				    }
				}
				catch (IntrospectionException e) {
					log.error("validServer"+" :: "+e);			
				}
				catch (IllegalAccessException e) {
					log.error("validServer"+" :: "+e);			
				}
				
				// check if changed
				if (oldValue!=null) {
					if (newValue!=null) {
						if (oldValue.equals(newValue)) {
							// not changed
						}
						else {
							generateNewXml = true;
							if (log.isDebugEnabled()) {
								log.debug("validServer"+" :: "+"attribute "+name+": "+oldValue+" --> "+newValue);
							}
						}
					}
					else {
						generateNewXml = true;
						if (log.isDebugEnabled()) {
							log.debug("validServer"+" :: "+"attribute "+name+": "+oldValue+" --> "+newValue);
						}
					}
				}
				else {
					if (newValue!=null) {
						generateNewXml = true;
						if (log.isDebugEnabled()) {
							log.debug("validServer"+" :: "+"attribute "+name+": "+oldValue+" --> "+newValue);
						}
					}
					else {
						// not changed
					}
				}
				
			}
			
			// the added spaces
			Vector addedSpaces = new Vector();
			
			// the deleted spaces
			Vector deletedSpaces = new Vector();

			// the spaces with targets changed
			Vector oldChangedSpacesTargets = new Vector();
			Vector newChangedSpacesTargets = new Vector();
			
			// for each space, we check the added spaces, and if attributes has changed
			ArrayList newSpaces = this.tempAdminServer.getSpaces();
			ArrayList oldSpaces = this.currentServer.getSpaces();
			for (int i=0; i<newSpaces.size(); i++) {
					
				Space newSpace = (Space)newSpaces.get(i);
					
				// look for the the old space
				Space oldSpace = null;
				for (int j=0; oldSpace==null && j<oldSpaces.size(); j++) {
					Space s = (Space)oldSpaces.get(j);
					if (s.getKey().equals(newSpace.getKey())) {
						oldSpace = s;
					}
				}
					
				// if not found; it's a new Space
				if (oldSpace == null) {
					addedSpaces.add(newSpace);
					if (log.isDebugEnabled()) {
						log.debug("validServer"+" :: "+"add space "+newSpace.getLabel());
					}
					generateNewXml = true;
				}
					
				// if found, we check the attributes
				else {
					
					// if targets changed
					if (!oldSpace.getTargetsOfSharing().equals(newSpace.getTargetsOfSharing())) {
						oldChangedSpacesTargets.add(oldSpace);
						newChangedSpacesTargets.add(newSpace);
						if (log.isDebugEnabled()) {
							log.debug("validServer"+" :: "+"modify space "+newSpace.getLabel());
						}
					}
					
					Vector spaceAttributes = getNewSpaceAttributesList(null, this.serverAttributes);
					for (int k=0; generateNewXml==false && k<spaceAttributes.size(); k++) {
						
						// the attribute
						Attribute a = (Attribute)spaceAttributes.elementAt(k);
						String name = a.getName();
						
						// the old value
						Class oldClass = oldSpace.getClass();
						String oldValue = null;
						
						// the new value
						Class newClass = newSpace.getClass();
						String newValue = null;
						
						
						try {
							
							// we use java refexion to find getter for old attribute
						    BeanInfo bi = Introspector.getBeanInfo(oldClass);
						    PropertyDescriptor[] propertyDescriptor = bi.getPropertyDescriptors();
						    for (int j=0; j<propertyDescriptor.length; j++) {
						    	if (propertyDescriptor[j].getName().equals(name)) {
						    		Method methodRead = propertyDescriptor[j].getReadMethod();
						    		try {
						    			oldValue = (String)methodRead.invoke(oldSpace, new Object[0]);
						    		}
						    		catch (InvocationTargetException e) {
										log.error("validServer"+" :: "+e);			
									}
						    		
						    		// no more nead to scan propertyDescriptor[] --> exit for statement
						    		j = propertyDescriptor.length;
						    	}
						    }
						    
							// we use java refexion to find getter for new attribute
						    bi = Introspector.getBeanInfo(newClass);
						    propertyDescriptor = bi.getPropertyDescriptors();
						    for (int j=0; j<propertyDescriptor.length; j++) {
						    	if (propertyDescriptor[j].getName().equals(name)) {
						    		Method methodRead = propertyDescriptor[j].getReadMethod();
						    		try {
						    			newValue = (String)methodRead.invoke(newSpace, new Object[0]);
						    		}
						    		catch (InvocationTargetException e) {
										log.error("validServer"+" :: "+e);			
									}
						    		
						    		// no more nead to scan propertyDescriptor[] --> exit for statement
						    		j = propertyDescriptor.length;
						    	}
						    }
						}
						catch (IntrospectionException e) {
							log.error("validServer"+" :: "+e);			
						}
						catch (IllegalAccessException e) {
							log.error("validServer"+" :: "+e);			
						}
						
						// check if changed
						if (oldValue!=null) {
							if (newValue!=null) {
								if (oldValue.equals(newValue)) {
									// not changed
								}
								else {
									generateNewXml = true;
									if (log.isDebugEnabled()) {
										log.debug("validServer"+" :: "+"attribute "+name+": "+oldValue+" --> "+newValue);
									}
								}
							}
							else {
								generateNewXml = true;
								if (log.isDebugEnabled()) {
									log.debug("validServer"+" :: "+"attribute "+name+": "+oldValue+" --> "+newValue);
								}
							}
						}
						else {
							if (newValue!=null) {
								generateNewXml = true;
								if (log.isDebugEnabled()) {
									log.debug("validServer"+" :: "+"attribute "+name+": "+oldValue+" --> "+newValue);
								}
							}
							else {
								// not changed
							}
						}
						
					}
				}
			}
			
			// check the deleted spaces
			for (int i=0; i<oldSpaces.size(); i++) {
				
				Space oldSpace = (Space)oldSpaces.get(i);
				
				// look for the the old space
				Space newSpace = null;
				for (int j=0; newSpace==null && j<newSpaces.size(); j++) {
					Space s = (Space)newSpaces.get(j);
					if (oldSpace.getKey().equals(s.getKey())) {
						newSpace = s;
					}
				}
				
				// if not found; it's a delete Space
				if (newSpace == null) {
					deletedSpaces.add(oldSpace);
					if (log.isDebugEnabled()) {
						log.debug("validServer"+" :: "+"delete space "+oldSpace.getLabel());
					}
					generateNewXml = true;
				}
			}
			
			// update
			adminTool.updateStorageAvailableAdministratedSpace(this.tempAdminServer, generateNewXml, addedSpaces, deletedSpaces, oldChangedSpacesTargets, newChangedSpacesTargets);
		}
		
	}
	
	
	
	/**
	 * Get a new list of attributes to set to the server
	 * @return a new list of attributes to set to the server
	 */
	private static Vector getNewServerAttributesList(Server server) {
		
		Vector serverAttributes = new Vector();
		
		// the url
		Attribute att = new Attribute(Attribute.URL);
		att.setObliged(true);
		serverAttributes.add(att);

		// the unauthenticatedServerUrl
		att = new Attribute(Attribute.UNAUTHENTICATED_SERVER_URL);
		att.setObliged(false);
		serverAttributes.add(att);

		// the injacPreviewUrl
		att = new Attribute(Attribute.INJAC_PREVIEW_URL);
		att.setObliged(false);
		serverAttributes.add(att);
		
		// the serverType
		att = new Attribute(Attribute.SERVER_TYPE);
		att.setObliged(true);
		att.setValue(Attribute.SERVER_TYPE_WEBDAV);
		Vector values = new Vector();
		values.add(Attribute.SERVER_TYPE_WEBDAV);
		values.add(Attribute.SERVER_TYPE_CIFS);
		att.setAvailableValues(values);
		serverAttributes.add(att);

		// the authenticationMode
		att = new Attribute(Attribute.AUTHENTICATION_MODE);
		att.setObliged(true);
		att.setValue(Attribute.AUTHENTICATION_MODE_ASKED);
		values = new Vector();
		values.add(Attribute.AUTHENTICATION_MODE_TRUSTED);
		values.add(Attribute.AUTHENTICATION_MODE_ASKED);
		att.setAvailableValues(values);
		serverAttributes.add(att);

		// the login
		att = new Attribute(Attribute.LOGIN);
		serverAttributes.add(att);

		// the password
		att = new Attribute(Attribute.PASSWORD);
		att.setInvisible(true);
		serverAttributes.add(att);

		// the manageAcl
		att = new Attribute(Attribute.MANAGE_ACL);
		att.setValue(Attribute.MANAGE_ACL_TRUE);
		values = new Vector();
		values.add(Attribute.MANAGE_ACL_TRUE);
		values.add(Attribute.MANAGE_ACL_FALSE);
		att.setAvailableValues(values);
		serverAttributes.add(att);

		// the aclNamespace
		att = new Attribute(Attribute.ACL_NAMESPACE);
		att.setObliged(true);
		serverAttributes.add(att);

		// the aclUserPrefix
		att = new Attribute(Attribute.ACL_USER_PREFIX);
		att.setObliged(true);
		serverAttributes.add(att);

		// the aclGroupPrefix
		att = new Attribute(Attribute.ACL_GROUP_PREFIX);
		att.setObliged(true);
		serverAttributes.add(att);

		// the aclUportalGroup
		att = new Attribute(Attribute.ACL_UPORTAL_GROUP);
		att.setObliged(true);
		serverAttributes.add(att);

		// the cifsDomain
		att = new Attribute(Attribute.CIFS_DOMAIN);
		att.setInvisible(true);
		serverAttributes.add(att);

		// the cifsResolveOrder
		att = new Attribute(Attribute.CIFS_RESOLVE_ORDER);
		att.setInvisible(true);
		serverAttributes.add(att);

		// the cifsDisablePlainTextPassword
		att = new Attribute(Attribute.CIFS_DISABLE_PLAIN_TEXT_PASSWORD);
		att.setInvisible(true);
		values = new Vector();
		values.add(Attribute.CIFS_DISABLE_PLAIN_TEXT_PASSWORD_TRUE);
		values.add(Attribute.CIFS_DISABLE_PLAIN_TEXT_PASSWORD_FALSE);
		att.setAvailableValues(values);
		serverAttributes.add(att);

		// the cifsUseUnicode
		att = new Attribute(Attribute.CIFS_USE_UNICODE);
		att.setInvisible(true);
		values = new Vector();
		values.add(Attribute.CIFS_USE_UNICODE_TRUE);
		values.add(Attribute.CIFS_USE_UNICODE_FALSE);
		att.setAvailableValues(values);
		serverAttributes.add(att);

		// the cifsEncoding
		att = new Attribute(Attribute.CIFS_ENCODING);
		att.setInvisible(true);
		serverAttributes.add(att);
		
		// if we still have values
		if (server!=null) {
			
			// for each attribute
			for (int k=0; k<serverAttributes.size(); k++) {
				
				Attribute a = (Attribute)serverAttributes.elementAt(k);
				String name = a.getName();
				
				Class c = server.getClass();
				String value = null;
				try {
					// we use java refexion to find getter and setter for attributeName
				    BeanInfo bi = Introspector.getBeanInfo(c);
				    PropertyDescriptor[] propertyDescriptor = bi.getPropertyDescriptors();
				    for (int i=0; i<propertyDescriptor.length; i++) {
				    	if (propertyDescriptor[i].getName().equals(name)) {
				    		Method methodRead = propertyDescriptor[i].getReadMethod();
				    		try {
				    			value = (String)methodRead.invoke(server, new Object[0]);
				    		}
				    		catch (InvocationTargetException e) {
								log.error("getNewServerAttributesList"+" :: "+e);			
							}
				    		
				    		if (value != null)
				    			a.setValue(value);
				    		
				    		// no more nead to scan propertyDescriptor[] --> exit for statement
				    		i = propertyDescriptor.length;
				    	}
				    }
				}
				/*catch (InvocationTargetException e) {
					log.error("getNewServerAttributesList"+" :: "+e);			
				}*/
				catch (IntrospectionException e) {
					log.error("getNewServerAttributesList"+" :: "+e);			
				}
				catch (IllegalAccessException e) {
					log.error("getNewServerAttributesList"+" :: "+e);			
				}
				
			}
			
			
			// check the rules of changement
			checkServerAttributesRules(serverAttributes);
			
		}
		
		
		// return the attributes		
		return serverAttributes;
	}
	
	
	
	
	/**
	 * Check if the attributes are well set
	 * @param runtimeData the ChannelRuntimeData object
	 * @param serverAttributes the list of attributes to set
	 * @return true if ok, false else
	 */
	private static boolean checkServerAttibutes(ChannelRuntimeData runtimeData, Vector serverAttributes, Server server) {
		
		// for each attribute, we check if it is changed
		Enumeration iter = serverAttributes.elements();
		while(iter.hasMoreElements()) {
			Attribute att = (Attribute)iter.nextElement();
			
			String name = att.getName();
			String oldValue = att.getValue();
			
			String newValue = runtimeData.getParameter(name);

			boolean change = false;
			if (newValue!=null) {
				if (oldValue==null || oldValue.trim().equals("")) {
					if (newValue==null || newValue.trim().equals("")) {
						change = false;
					}
					else {
						change=true;
					}
				}
				else {
					if (oldValue.equals(newValue)) {
						change = false;
					}
					else {
						change = true;
					}
				}
			}
			
			// if change
			if (change) {
				
				if (att.isModifiable()) {
					att.setValue(newValue);
				}
			}
		}
		
		// check the rules of changement
		checkServerAttributesRules(serverAttributes);
		
		// put each attribute into the server object
		for (int k=0; k<serverAttributes.size(); k++) {
			
			Attribute a = (Attribute)serverAttributes.elementAt(k);
			String name = a.getName();
			
			String value = a.getValue();
			
			Class c = server.getClass();
			try {
				// we use java refexion to find getter and setter for attributeName
			    BeanInfo bi = Introspector.getBeanInfo(c);
			    PropertyDescriptor[] propertyDescriptor = bi.getPropertyDescriptors();
			    for (int i=0; i<propertyDescriptor.length; i++) {
			    	if (propertyDescriptor[i].getName().equals(name)) {
			    		Method methodWrite = propertyDescriptor[i].getWriteMethod();
			    		Object[] obj = new Object[1];
			    		obj[0] = value;
			    		methodWrite.invoke(server, obj);
			    		
			    		// no more nead to scan propertyDescriptor[] --> exit for statement
			    		i = propertyDescriptor.length;
			    	}
			    }
			}
			catch (InvocationTargetException e) {
				log.error("validServer"+" :: "+e);			
			}
			catch (IntrospectionException e) {
				log.error("validServer"+" :: "+e);			
			}
			catch (IllegalAccessException e) {
				log.error("validServer"+" :: "+e);			
			}
			
		}
		
		// check if it is ok		
		iter = serverAttributes.elements();
		while(iter.hasMoreElements()) {
			Attribute att = (Attribute)iter.nextElement();
			if (!att.isGoodFormat()) {
				return false;
			}
		}
		return true;
	}
	
	

	/**
	 * If somme attributes change, we have to change others ones
	 * @param serverAttributes
	 */
	private static void checkServerAttributesRules(Vector serverAttributes) {//TODO

		// serverType
		Attribute serverType = (Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.SERVER_TYPE)));
		String value = serverType.getValue();
		
		// if webdav
		if (value!=null && value.equals(Attribute.SERVER_TYPE_WEBDAV)) {
				
			// disable cifs attributes
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_DOMAIN)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_RESOLVE_ORDER)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_DISABLE_PLAIN_TEXT_PASSWORD)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_USE_UNICODE)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_ENCODING)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_DOMAIN)))).setValue(null);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_RESOLVE_ORDER)))).setValue(null);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_DISABLE_PLAIN_TEXT_PASSWORD)))).setValue(null);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_USE_UNICODE)))).setValue(null);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_ENCODING)))).setValue(null);
			
			// set manageAcl to false
			Attribute a = (Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.MANAGE_ACL)));
			a.setModifiable(true);
			
			// public url and injac url
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.UNAUTHENTICATED_SERVER_URL)))).setInvisible(false);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.INJAC_PREVIEW_URL)))).setInvisible(false);
		}
		
		// if cifs
		else if (value!=null && value.equals(Attribute.SERVER_TYPE_CIFS)) {
			
			// disable cifs attributes
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_DOMAIN)))).setInvisible(false);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_RESOLVE_ORDER)))).setInvisible(false);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_DISABLE_PLAIN_TEXT_PASSWORD)))).setInvisible(false);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_USE_UNICODE)))).setInvisible(false);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.CIFS_ENCODING)))).setInvisible(false);
				
			// set manageAcl to false
			Attribute a = (Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.MANAGE_ACL)));
			a.setValue(Attribute.MANAGE_ACL_FALSE);
			a.setModifiable(false);
			
			// disable acl attributes
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_NAMESPACE)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_USER_PREFIX)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_GROUP_PREFIX)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_UPORTAL_GROUP)))).setInvisible(true);
			//TODO((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_NAMESPACE)))).setValue(null);
			//TODO((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_USER_PREFIX)))).setValue(null);
			//TODO((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_GROUP_PREFIX)))).setValue(null);
			//TODO((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_UPORTAL_GROUP)))).setValue(null);
			
			// public url and injac url
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.UNAUTHENTICATED_SERVER_URL)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.INJAC_PREVIEW_URL)))).setInvisible(true);
				
		}
		
	
		// manageAcl
		Attribute manageAcl = (Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.MANAGE_ACL)));
		value = manageAcl.getValue();

		// if true
		if (value!=null && value.equals(Attribute.MANAGE_ACL_TRUE)) {
			
			// enable acl attributes
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_NAMESPACE)))).setObliged(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_USER_PREFIX)))).setObliged(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_GROUP_PREFIX)))).setObliged(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_UPORTAL_GROUP)))).setObliged(true);
				
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_NAMESPACE)))).setInvisible(false);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_USER_PREFIX)))).setInvisible(false);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_GROUP_PREFIX)))).setInvisible(false);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_UPORTAL_GROUP)))).setInvisible(false);

			// public url and injac url
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.UNAUTHENTICATED_SERVER_URL)))).setInvisible(false);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.INJAC_PREVIEW_URL)))).setInvisible(false);
		}
		
		// if false
		else if (value!=null && value.equals(Attribute.MANAGE_ACL_FALSE)) {
			
			// disable acl attributes
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_NAMESPACE)))).setObliged(false);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_USER_PREFIX)))).setObliged(false);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_GROUP_PREFIX)))).setObliged(false);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_UPORTAL_GROUP)))).setObliged(false);
				
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_NAMESPACE)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_USER_PREFIX)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_GROUP_PREFIX)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_UPORTAL_GROUP)))).setInvisible(true);
			//TODO((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_NAMESPACE)))).setValue(null);
			//TODO((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_USER_PREFIX)))).setValue(null);
			//TODO((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_GROUP_PREFIX)))).setValue(null);
			//TODO((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.ACL_UPORTAL_GROUP)))).setValue(null);

			// public url and injac url
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.UNAUTHENTICATED_SERVER_URL)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.INJAC_PREVIEW_URL)))).setInvisible(true);
				
		}
		

		// authenticationMode
		Attribute authenticationMode = (Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.AUTHENTICATION_MODE)));
		value = authenticationMode.getValue();

		// if trusted
		if (value!=null && value.equals(Attribute.AUTHENTICATION_MODE_TRUSTED)) {
			
			// enable password
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.PASSWORD)))).setObliged(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.PASSWORD)))).setInvisible(false);
				
		}
		
		// if asked
		else if (value!=null && value.equals(Attribute.AUTHENTICATION_MODE_ASKED)) {
			
			// disable password
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.PASSWORD)))).setObliged(false);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.PASSWORD)))).setInvisible(true);
			((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.PASSWORD)))).setValue(null);
				
		}
		
	}
	

	/**
	 * Confirm when we ask to delete a server
	 * @param runtimeData the ChannelRuntimeData object
	 * @return the xml
	 */
	private StringBuffer renderXmlConfirmDeleteServer(ChannelRuntimeData runtimeData) {
		
		String ind = runtimeData.getParameter("index");
		int index = Integer.parseInt(ind);
		
		Server s = (Server)this.servers.elementAt(index);
		String name = s.getName();
		String serverId = s.getId();
		
		StringBuffer xml = new StringBuffer();
		xml.append("<name>"+name+"</name>");
		xml.append("<server_id>"+serverId+"</server_id>");
		return xml;
	}
	
	

	/**
	 * delete a server
	 * @param runtimeData the ChannelRuntimeData object
	 * @throws DataBaseException
	 */
	private void deleteServer(ChannelRuntimeData runtimeData) throws DataBaseException {
		
		// if confirm
		String submit = runtimeData.getParameter("Submit");
		if (submit!=null) {
			
			String serverId = runtimeData.getParameter("server_id");
			Server server = null;
			for (int i=0; server==null && i<servers.size(); i++) {
				Server s = (Server)servers.elementAt(i);
				if (serverId.equals(s.getId())) {
					server = s;
				}
				
			}
			
			this.adminTool.delStorageAvailableAdministratedServer(server);
		}
		
	}


	/**
	 * Confirm when we ask to rename a server
	 * @param runtimeData the ChannelRuntimeData object
	 * @return the xml
	 */
	private StringBuffer renderXmlConfirmRenameServer(ChannelRuntimeData runtimeData) {
		
		String ind = runtimeData.getParameter("index");
		int index = Integer.parseInt(ind);
		
		Server s = (Server)this.servers.elementAt(index);
		String name = s.getName();
		String serverId = s.getId();
		
		StringBuffer xml = new StringBuffer();
		xml.append("<old_name>"+name+"</old_name>");
		xml.append("<server_id>"+serverId+"</server_id>");
		return xml;
	}
	
	

	/**
	 * Rename a server
	 * @param runtimeData the ChannelRuntimeData object
	 * @throws DataBaseException
	 * @throws StillExistsServerException
	 */
	private void renameServer(ChannelRuntimeData runtimeData) throws DataBaseException, StillExistsServerException {
		
		// if confirm
		String submit = runtimeData.getParameter("Submit");
		if (submit!=null) {
			
			String newName = runtimeData.getParameter("new_name");

			// check if this name is still used
			boolean found = false;
			for (int i=0; servers!=null && i<servers.size(); i++) {
				Server s = (Server)servers.elementAt(i);
				if (s.getName().toLowerCase().equals(newName.toLowerCase())) {
					found = true;
				}
			}
			if (found) {
				StillExistsServerException e = new StillExistsServerException();
				
				// log
				if (log.isDebugEnabled()){
					log.debug("renameServer"+" :: "+e);
				}
				
				throw e;
			}
			
			String serverId = runtimeData.getParameter("server_id");
			Server server = null;
			for (int i=0; server==null && i<servers.size(); i++) {
				Server s = (Server)servers.elementAt(i);
				if (serverId.equals(s.getId())) {
					server = s;
				}
				
			}
			
			this.adminTool.updateServerNameAvailableSpace(serverId, newName);
		}
		
	}

	/**************************
	 *  Administration space
	 **************************/

	
	/**
	 * The attributes to set the space
	 */
	private Vector spaceAttributes;

	/**
	 * The space we are editing
	 */
	private Space currentSpace;
	

	/**
	 * sharing directory properties used during the sharing management
	 */
	private Space tempAdminSpace;
	
	
	
	
	

	/**
	 * Return the xml for the default space mode
	 * @param runtimeData the ChannelRuntimeData object
	 * @return the xml for the default space mode
	 * @throws CancelException
	 */
	private StringBuffer renderXmlDefaultSpace(ChannelRuntimeData runtimeData, ContentHandler out) throws DataBaseException, PropertiesException, PortalException, CancelException {
		
		// if it is a new Space
		String newSpace = runtimeData.getParameter("new_space");
		if (newSpace!=null && newSpace.equals("true")) {
			this.currentSpace = new Space();
			this.currentSpace.setServer(this.tempAdminServer);
			/*if (this.currentSpace.getServer().getSpaces()==null || this.currentSpace.getServer().getSpaces().size()==0) {
				ArrayList spaces = new ArrayList();
				spaces.add(this.currentSpace);
				this.currentSpace.getServer().setSpaces(spaces);
			}
			else {
				this.currentSpace.getServer().getSpaces().add(this.currentSpace);
			}*/
			//this.currentSpace.setLabel("nouv");
			DirectorySharingProperties sh = new DirectorySharingProperties(null);
			this.currentSpace.setTargetsOfSharing(sh);
			this.tempAdminSpace = (Space)this.currentSpace.clone();
		}
		
		else {

			// if we delete a space
			String deleteSpace = runtimeData.getParameter("delete_space");
			if (deleteSpace!=null && deleteSpace.equals("true")) {
				stylesheet = new StringBuffer("confirmDeleteSpace");
				return renderXmlConfirmDeleteSpace(runtimeData);		
			}
			
			else {

				// if we select a space
				String ind = runtimeData.getParameter("index_space");
				if (ind!=null) {
					int index = Integer.parseInt(ind);
					this.currentSpace = (Space)this.tempAdminServer.getSpaces().get(index);
					this.tempAdminSpace = (Space)this.currentSpace.clone();
				}
			}
		}
		


		// check the attributes
		boolean attributesOk = false;
		
		// init the attributes
		if (spaceAttributes==null) {
			spaceAttributes = getNewSpaceAttributesList(this.tempAdminSpace, this.serverAttributes);
			checkSpaceAttributesRules(spaceAttributes, serverAttributes);
		}
		else {
			attributesOk = checkSpaceAttibutes(runtimeData, spaceAttributes, serverAttributes);

			// check users and groups
			checkUsersAndGroups(runtimeData);
		}
		
		// get the mode
		String mode = runtimeData.getParameter("mode");
		
		// if valid
		if (mode!=null && mode.equals("validSpace")) {

			// check users and groups
			checkUsersAndGroups(runtimeData);
			
			if (!attributesOk) {
				return getDefaultSpaceXml(runtimeData);
			}
			else {
				validSpace(runtimeData);
				spaceAttributes = null;
				
				stylesheet = new StringBuffer("server");
				return getDefaultServerXml(runtimeData);
			}
		}

		// if cancel
		if (mode!=null && mode.equals("cancelSpace")) {
			spaceAttributes = null;
			/*System.out.println("je veux effacer "+this.tempAdminSpace.getKey()+" et j'ai ");
			for (int i=0; i<this.tempAdminServer.getSpaces().size(); i++) {
				System.out.println(i+") "+this.tempAdminServer.getSpaces().get(i));
			}
			this.tempAdminServer.getSpaces().remove(this.tempAdminSpace);
			System.out.println("et apres "+this.tempAdminSpace.getKey()+" j'ai ");
			for (int i=0; i<this.tempAdminServer.getSpaces().size(); i++) {
				System.out.println(i+") "+this.tempAdminServer.getSpaces().get(i));
			}*/
			this.currentSpace = null;
			this.tempAdminSpace = null;
			this.stylesheet = new StringBuffer("server");
			return getDefaultServerXml(runtimeData);
		}
		
		// if click on add user
		String addUserButton = runtimeData.getParameter("add_user");
		if (addUserButton != null)
			return renderXmlShareDirectoryAddUser(runtimeData, staticData, out);
			
		// if click on add group
		String addGroupButton = runtimeData.getParameter("add_group");
		if (addGroupButton != null)
			return renderXmlShareDirectoryAddGroup(runtimeData, staticData, out);
		
		// if click on delete user
		String deleteUserButton = runtimeData.getParameter("delete_user");
		if (deleteUserButton != null)
			return renderXmlShareDirectoryDeleteUser(runtimeData);
			
		// if click on delete group
		String deleteGroupButton = runtimeData.getParameter("delete_group");
		if (deleteGroupButton != null)
			return renderXmlShareDirectoryDeleteGroup(runtimeData);
			
		// default XML
		return getDefaultSpaceXml(runtimeData);
	}
	


	/**
	 * Return the xml for the default space mode
	 * @param runtimeData the ChannelRuntimeData object
	 * @return the xml for the default space mode
	 */
	public StringBuffer getDefaultSpaceXml(ChannelRuntimeData runtimeData) {
		StringBuffer xml = new StringBuffer();
		
		xml.append("<space>\n");
		
		xml.append(getSpaceAttributesXml(spaceAttributes));
		xml.append(getSpaceUsersAndGroupsXml(this.tempAdminSpace.getTargetsOfSharing()));
		
		xml.append("</space>\n");
		
		return xml;
	}
	
	
	
	/**
	 * Get the XML for the attributes
	 * @param spaceAttributes the list of attributes to set
	 * @return the xml generated
	 */
	private static StringBuffer getSpaceAttributesXml(Vector spaceAttributes) {
		
		StringBuffer xml = new StringBuffer();
		xml.append("<attributes>\n");
		
		if (spaceAttributes!=null) {
			
			Enumeration iter = spaceAttributes.elements();
			while(iter.hasMoreElements()) {
				
				Attribute att = (Attribute)iter.nextElement();
				if (!att.isInvisible()) {
					
					// if select area
					if (!(att.getAvailableValues()==null || att.getAvailableValues().size()==0) && att.isModifiable()) {
						xml.append("<attribute input=\"select\" name=\""+att.getName()+"\" value=\""+att.getValue()+"\" obliged=\""+att.isObliged()+"\" goodFormat=\""+att.isGoodFormat()+"\" >\n");
						for (int i=0; i<att.getAvailableValues().size(); i++) {
							String val = (String)att.getAvailableValues().elementAt(i);
							xml.append("<choice value=\""+val+"\"/>\n");
						}
						xml.append("</attribute>\n");
					}
					
					// if text area
					else {
						if (att.getValue() == null) {
							xml.append("<attribute input=\"text\" name=\""+att.getName()+"\" value=\""+""+"\" obliged=\""+att.isObliged()+"\" goodFormat=\""+att.isGoodFormat()+"\" modifiable=\""+att.isModifiable()+"\"  />\n");
						}
						else {
							xml.append("<attribute input=\"text\" name=\""+att.getName()+"\" value=\""+att.getValue()+"\" obliged=\""+att.isObliged()+"\" goodFormat=\""+att.isGoodFormat()+"\" modifiable=\""+att.isModifiable()+"\"  />\n");	
						}
					}
					
				}
			}
			
		}
		
		xml.append("</attributes>\n");
		return xml;
	}


	/**
	 * Get the XML for the users ans groups
	 * @param sharingProperties the properties for the sharing
	 * @return the xml generated
	 */
	private static StringBuffer getSpaceUsersAndGroupsXml(DirectorySharingProperties sharingProperties) {
		return sharingProperties.getXml(null, false, null);
	}
	

	
	
	
	/**
	 * Valid the space's settings
	 * @param runtimeData
	 */
	private void validSpace(ChannelRuntimeData runtimeData) {
		

		// for each attribute, we set it into the currentServer
		//System.out.println(currentServer);
		for (int k=0; k<spaceAttributes.size(); k++) {
			
			Attribute a = (Attribute)spaceAttributes.elementAt(k);
			String name = a.getName();
			String value = a.getValue();
			
			Class c = this.currentSpace.getClass();
			try {
				// we use java refexion to find getter and setter for attributeName
			    BeanInfo bi = Introspector.getBeanInfo(c);
			    PropertyDescriptor[] propertyDescriptor = bi.getPropertyDescriptors();
			    for (int i=0; i<propertyDescriptor.length; i++) {
			    	if (propertyDescriptor[i].getName().equals(name)) {
			    		Method methodWrite = propertyDescriptor[i].getWriteMethod();
			    		Object[] obj = new Object[1];
			    		obj[0] = value;
			    		methodWrite.invoke(this.currentSpace, obj);
			    		
			    		// no more nead to scan propertyDescriptor[] --> exit for statement
			    		i = propertyDescriptor.length;
			    	}
			    }
			}
			catch (InvocationTargetException e) {
				log.error("validSpace"+" :: "+e);			
			}
			catch (IntrospectionException e) {
				log.error("validSpace"+" :: "+e);			
			}
			catch (IllegalAccessException e) {
				log.error("validSpace"+" :: "+e);			
			}
			
		}
		//System.out.println(currentServer);
		
		// check users and groups
		//checkUsersAndGroups(runtimeData);
		
		// set temporary users and groups into the current space
		this.currentSpace.setTargetsOfSharing(this.tempAdminSpace.getTargetsOfSharing());
		
		// if this space is new, we add it into the server
		if (this.currentSpace.getKey() == null) {
			
			// check if this space is still inside
			boolean inside = false;
			ArrayList spaces = this.tempAdminServer.getSpaces();
			for (int i=0; !inside && i<spaces.size(); i++) {
				Space s = (Space)spaces.get(i);
				if (s == this.currentSpace) {
					inside = true;
				}
			}
			if (!inside) {
				this.tempAdminServer.getSpaces().add(this.currentSpace);
				
			}
			
		}
		
	}
	
	
	
	/**
	 * Get a new list of attributes to set to the space
	 * @return a new list of attributes to set to the space
	 */
	private static Vector getNewSpaceAttributesList(Space space, Vector serverAttributes) {
		
		Vector spaceAttributes = new Vector();
		
		// the label
		Attribute att = new Attribute(Attribute.LABEL);
		att.setObliged(true);
		spaceAttributes.add(att);

		// the path
		att = new Attribute(Attribute.PATH);
		att.setObliged(true);
		spaceAttributes.add(att);

		// the pathRegexp
		att = new Attribute(Attribute.PATH_REGEXP);
		att.setObliged(false);
		spaceAttributes.add(att);

		// the pathRegexpSeparator
		att = new Attribute(Attribute.PATH_REGEXP_SEPARATOR);
		att.setObliged(false);
		spaceAttributes.add(att);

		// the actionType
		att = new Attribute(Attribute.ACTION_TYPE);
		att.setObliged(true);
		att.setValue(Attribute.ACTION_TYPE_CLASSIC);
		Vector values = new Vector();
		values.add(Attribute.ACTION_TYPE_CLASSIC);
		values.add(Attribute.ACTION_TYPE_INJAC);
		att.setAvailableValues(values);
		spaceAttributes.add(att);

		// the sharing
		att = new Attribute(Attribute.SHARING);
		spaceAttributes.add(att);
		if (((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.MANAGE_ACL)))).getValue().equals(Attribute.MANAGE_ACL_FALSE)) {
			att.setObliged(false);
			att.setInvisible(true);
			att.setValue(Attribute.SHARING_TRUE);
			values = new Vector();
			values.add(Attribute.SHARING_TRUE);
			values.add(Attribute.SHARING_FALSE);
			att.setAvailableValues(values);
		}
		else {
			att.setObliged(true);
			att.setInvisible(false);
			att.setValue(Attribute.SHARING_TRUE);
			values = new Vector();
			values.add(Attribute.SHARING_TRUE);
			values.add(Attribute.SHARING_FALSE);
			att.setAvailableValues(values);
		}
		
		// the aclSecurity
		att = new Attribute(Attribute.ACL_SECURITY);
		spaceAttributes.add(att);
		if (((Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.MANAGE_ACL)))).getValue().equals(Attribute.MANAGE_ACL_FALSE)) {
			att.setObliged(false);
			att.setInvisible(true);
		}
		else {
			att.setObliged(true);
			att.setInvisible(false);
		}
		
		// if we still have values
		if (space!=null) {
			
			// for each attribute
			for (int k=0; k<spaceAttributes.size(); k++) {
				
				Attribute a = (Attribute)spaceAttributes.elementAt(k);
				String name = a.getName();
				
				Class c = space.getClass();
				String value = null;
				try {
					// we use java refexion to find getter and setter for attributeName
				    BeanInfo bi = Introspector.getBeanInfo(c);
				    PropertyDescriptor[] propertyDescriptor = bi.getPropertyDescriptors();
				    for (int i=0; i<propertyDescriptor.length; i++) {
				    	if (propertyDescriptor[i].getName().equals(name)) {
				    		Method methodRead = propertyDescriptor[i].getReadMethod();
				    		try {
				    			value = (String)methodRead.invoke(space, new Object[0]);
				    		}
				    		catch (InvocationTargetException e) {
								log.error("getNewSpaceAttributesList"+" :: "+e);			
							}
				    		
				    		if (value != null)
				    			a.setValue(value);
				    		
				    		// no more nead to scan propertyDescriptor[] --> exit for statement
				    		i = propertyDescriptor.length;
				    	}
				    }
				}
				/*catch (InvocationTargetException e) {
					log.error("getNewSpaceAttributesList"+" :: "+e);			
				}*/
				catch (IntrospectionException e) {
					log.error("getNewSpaceAttributesList"+" :: "+e);			
				}
				catch (IllegalAccessException e) {
					log.error("getNewSpaceAttributesList"+" :: "+e);			
				}
				
			}
			
			// check the rules of changement
			checkSpaceAttributesRules(spaceAttributes, serverAttributes);
		}
		
		
		// return the attributes		
		return spaceAttributes;
	}
	
	
	
	
	/**
	 * Check if the attributes are well set
	 * @param runtimeData the ChannelRuntimeData object
	 * @param spaceAttributes the list of attributes to set
	 * @return true if ok, false else
	 */
	private static boolean checkSpaceAttibutes(ChannelRuntimeData runtimeData, Vector spaceAttributes, Vector serverAttributes) {
		
		// for each attribute, we check if it is changed
		Enumeration iter = spaceAttributes.elements();
		while(iter.hasMoreElements()) {
			Attribute att = (Attribute)iter.nextElement();
			
			String name = att.getName();
			String oldValue = att.getValue();
			
			String newValue = runtimeData.getParameter(name);

			boolean change = false;
			if (newValue!=null) {
				if (oldValue==null || oldValue.trim().equals("")) {
					if (newValue==null || newValue.trim().equals("")) {
						change = false;
					}
					else {
						change=true;
					}
				}
				else {
					if (oldValue.equals(newValue)) {
						change = false;
					}
					else {
						change = true;
					}
				}
			}
			
			// if change
			if (change) {
				
				if (att.isModifiable()) {
					
					att.setValue(newValue);
				
				}	
			}
		}
		

		// check the rules of changement
		checkSpaceAttributesRules(spaceAttributes, serverAttributes);
		
		
		// check if it is ok		
		iter = spaceAttributes.elements();
		while(iter.hasMoreElements()) {
			Attribute att = (Attribute)iter.nextElement();
			if (!att.isGoodFormat()) {
				return false;
			}
		}
		return true;
	}
	
	
	

	/**
	 * If somme attributes change, we have to change others ones
	 * @param spaceAttributes
	 */
	private static void checkSpaceAttributesRules(Vector spaceAttributes, Vector serverAttributes) {//TODO
		
		// manageAcl
		Attribute manageAcl = (Attribute)serverAttributes.get(serverAttributes.indexOf(new Attribute(Attribute.MANAGE_ACL)));
		String value = manageAcl.getValue();
		
		// if true
		if (value!=null && value.equals(Attribute.MANAGE_ACL_TRUE)) {

			// classic or injac
			Attribute actionType = (Attribute)spaceAttributes.get(spaceAttributes.indexOf(new Attribute(Attribute.ACTION_TYPE)));
			value = actionType.getValue();
			
			// if classic
			if (value!=null && value.equals(Attribute.ACTION_TYPE_CLASSIC)) {
				
				((Attribute)spaceAttributes.get(spaceAttributes.indexOf(new Attribute(Attribute.SHARING)))).setInvisible(false);
				
				String sharing = ((Attribute)spaceAttributes.get(spaceAttributes.indexOf(new Attribute(Attribute.SHARING)))).getValue();
				
				// if sharing
				if (sharing!=null && sharing.equals(Attribute.SHARING_TRUE)) {
					
					((Attribute)spaceAttributes.get(spaceAttributes.indexOf(new Attribute(Attribute.ACL_SECURITY)))).setInvisible(false);
					((Attribute)spaceAttributes.get(spaceAttributes.indexOf(new Attribute(Attribute.ACL_SECURITY)))).setObliged(true);
				}
				
				// not sharing
				else if (sharing!=null && sharing.equals(Attribute.SHARING_FALSE)) {
					
					((Attribute)spaceAttributes.get(spaceAttributes.indexOf(new Attribute(Attribute.ACL_SECURITY)))).setInvisible(true);
					((Attribute)spaceAttributes.get(spaceAttributes.indexOf(new Attribute(Attribute.ACL_SECURITY)))).setObliged(false);
				}
				
			}
			
			// if false
			else if (value!=null && value.equals(Attribute.ACTION_TYPE_INJAC)) {
				
				((Attribute)spaceAttributes.get(spaceAttributes.indexOf(new Attribute(Attribute.SHARING)))).setInvisible(true);
				((Attribute)spaceAttributes.get(spaceAttributes.indexOf(new Attribute(Attribute.SHARING)))).setObliged(false);
				
				((Attribute)spaceAttributes.get(spaceAttributes.indexOf(new Attribute(Attribute.ACL_SECURITY)))).setInvisible(false);
				((Attribute)spaceAttributes.get(spaceAttributes.indexOf(new Attribute(Attribute.ACL_SECURITY)))).setObliged(true);
			}
			
		}
		
		// if false
		else if (value!=null && value.equals(Attribute.MANAGE_ACL_FALSE)) {
			((Attribute)spaceAttributes.get(spaceAttributes.indexOf(new Attribute(Attribute.ACL_SECURITY)))).setInvisible(true);
			((Attribute)spaceAttributes.get(spaceAttributes.indexOf(new Attribute(Attribute.ACL_SECURITY)))).setObliged(false);
		}
				
	}

	
	
	

	/**
	 * When valid the sharing
	 * @param runtimeData
	 */
	private void checkUsersAndGroups(ChannelRuntimeData runtimeData) {//TODO
		
		// get the obliged lists
		String[] obligedUserList = runtimeData.getParameterValues("obligedUserList");
		String[] obligedGroupList = runtimeData.getParameterValues("obligedGroupList");
		
		// get the users and the groups
		Vector users = tempAdminSpace.getTargetsOfSharing().getUsers();
		Vector groups = tempAdminSpace.getTargetsOfSharing().getGroups();
		
		// for each user, we check if he has read and/or write rights
		Enumeration iter = users.elements();
		while (iter.hasMoreElements()) {
			UserForPersonalization u = (UserForPersonalization)iter.nextElement();
			String key = u.getKey();

			// check if he is obliged
			boolean contains = false;
			for (int i=0; obligedUserList!=null && i<obligedUserList.length && !contains; i++) {
				if (obligedUserList[i].equals(key))
					contains = true;
			}			
			if (contains) {
				u.getPersonalization().setObliged(true);
			}
			else {
				u.getPersonalization().setObliged(false);
			}
			
		}

		// for each group, we check if he has read and/or write rights
		iter = groups.elements();
		while (iter.hasMoreElements()) {
			GroupForPersonalization g = (GroupForPersonalization)iter.nextElement();
			String key = g.getKey();

			// check if he is obliged
			boolean contains = false;
			for (int i=0; obligedGroupList!=null && i<obligedGroupList.length && !contains; i++) {
				if (obligedGroupList[i].equals(key))
					contains = true;
			}			
			if (contains) {
				g.getPersonalization().setObliged(true);
			}
			else {
				g.getPersonalization().setObliged(false);
			}
			
		}
	}
	
	

	/**
	 * When we want to add a user
	 * @param runtimeData the runtime data object used in this channel
	 * @param staticData the static data object used in this channel
	 * @param out the output object used for the rendering
	 * @return the xml when we add somebody
	 * @throws PropertiesException
	 * @throws PortalException
	 */
	private StringBuffer renderXmlShareDirectoryAddUser(ChannelRuntimeData runtimeData, ChannelStaticData staticData, ContentHandler out) throws PropertiesException, PortalException {		
		
		//stylesheet = new StringBuffer();
		
		// check the parameters
		checkUsersAndGroups(runtimeData);
		
		staticData.setParameter("returnServant", "multiple");
		slave = CAnnuaireServantFactory.getAnnuaireServant(staticData);

		slave.setRuntimeData(runtimeData);		
		slave.renderXML(out);	
	
		return null;
	}
	
	
	
	
	

	/**
	 * When we want to add a group
	 * @param runtimeData the runtime data object used in this channel
	 * @param staticData the static data object used in this channel
	 * @param out the output object used for the rendering
	 * @return the xml when we add somebody
	 * @throws PropertiesException
	 * @throws PortalException
	 */
	private StringBuffer renderXmlShareDirectoryAddGroup(ChannelRuntimeData runtimeData, ChannelStaticData staticData, ContentHandler out) throws PropertiesException, PortalException {		

		// check the parameters
		checkUsersAndGroups(runtimeData);
		
		slave = CGroupsManagerServantFactory.getGroupsServantforSelection(staticData, null, GroupService.EVERYONE, true, true);

		slave.setRuntimeData(runtimeData);		
		slave.renderXML(out);
	
		return null;
	}
	
	

	/**
	 * When we delete a user
	 * @param runtimeData the runtime data object used in the channel
	 * @return the xml when we delete somebody
	 * @throws PropertiesException
	 */
	private StringBuffer renderXmlShareDirectoryDeleteUser(ChannelRuntimeData runtimeData) throws PropertiesException {

		// check the parameters
		checkUsersAndGroups(runtimeData);
		
		// the selection
		String[] selection = selection = runtimeData.getParameterValues("usersList");
		
		// if none selected
		if (selection==null || selection.length==0)
			return getDefaultSpaceXml(runtimeData);

		// for each user, we delete it
		Vector users = this.tempAdminSpace.getTargetsOfSharing().getUsers();

		// for each selection
		for (int i=0; i<selection.length; i++) {
			
			// for each user
			boolean found = false;
			for (int j=0; !found && j<users.size(); j++) {
				UserForPersonalization u =(UserForPersonalization)users.elementAt(j);
				if (u.getKey().equals(selection[i])) {
					users.remove(j);
				}
			}
			
		}
		
		return getDefaultSpaceXml(runtimeData);
	}
	
	
	
	

	
	/**
	 * When we delete a group
	 * @param runtimeData the runtime data object used in the channel
	 * @return the xml when we delete somebody
	 * @throws PropertiesException
	 */
	private StringBuffer renderXmlShareDirectoryDeleteGroup(ChannelRuntimeData runtimeData) throws PropertiesException {

		// check the parameters
		checkUsersAndGroups(runtimeData);
		
		// the selection
		String[] selection = selection = runtimeData.getParameterValues("groupsList");
		
		// if none selected
		if (selection==null || selection.length==0)
			return getDefaultSpaceXml(runtimeData);
		
		// for each group, we delete it
		Vector groups = this.tempAdminSpace.getTargetsOfSharing().getGroups();
		for (int i=0; i<selection.length; i++) {

			// for each group
			boolean found = false;
			for (int j=0; !found && j<groups.size(); j++) {
				GroupForPersonalization g =(GroupForPersonalization)groups.elementAt(j);
				if (g.getKey().equals(selection[i])) {
					groups.remove(j);
				}
			}
		}
		
		return getDefaultSpaceXml(runtimeData);
	}
	
	
	

	
	/**
	 * When we check the servant results
	 * @param runtimeData the runtime data object used in this channel 
	 * @param staticData the static data object used in this channel
	 * @return the xml after getting the servant results
	 * @throws PropertiesException
	 */
	private StringBuffer renderXmlValidServantResults(ChannelRuntimeData runtimeData, ChannelStaticData staticData, ContentHandler out) throws PropertiesException, PortalException, DataBaseException, CancelException { 
		
		// get the results
		Object[] objs = slave.getResults();
		if (objs!=null) {
			for (int i=0; i<objs.length; i++) {
				Object obj = objs[i];
			
				// if we have a people from the CAnnuaire servant
				if (obj instanceof org.esupportail.portal.channels.CAnnuaire.Personne) {
					org.esupportail.portal.channels.CAnnuaire.Personne pers = (org.esupportail.portal.channels.CAnnuaire.Personne)obj;
					
					UserForPersonalization user = new UserForPersonalization(pers);
					user.getPersonalization().setReading(1);
					if (!this.tempAdminSpace.getTargetsOfSharing().getUsers().contains(user))
						this.tempAdminSpace.getTargetsOfSharing().getUsers().addElement(user);
				}
			
				// if we have a group from the CGroupManager servant
				else if (obj instanceof org.jasig.portal.groups.EntityGroupImpl) {
					EntityGroupImpl egi = (EntityGroupImpl)obj;
					String leafType = egi.getLeafType().getName();
				
					// if the selection is really a group of persons
					if (leafType.equals("org.jasig.portal.security.IPerson")) {					
					
						try {
							GroupForPersonalization group = new GroupForPersonalization(egi);
							group.getPersonalization().setReading(1);
							if (!this.tempAdminSpace.getTargetsOfSharing().getGroups().contains(group))
								this.tempAdminSpace.getTargetsOfSharing().getGroups().addElement(group);
						}
						catch(ServerException e) {							
							log.error("renderXmlValidServantResults"+" :: "+e);							
						}
					}
				}									
			}
		}
		
		slave = null;		
		staticData.setParameter("groupManagerFinished", "false");	
		return renderXmlDefaultSpace(runtimeData, out);
	}
	
	
	
	
	
	/**
	 * Confirm when we ask to delete a space
	 * @param runtimeData the ChannelRuntimeData object
	 * @return the xml
	 */
	private StringBuffer renderXmlConfirmDeleteSpace(ChannelRuntimeData runtimeData) {
		
		String ind = runtimeData.getParameter("index_space");
		int index = Integer.parseInt(ind);
		
		Space s = (Space)this.tempAdminServer.getSpaces().get(index);
		String label = s.getLabel();
		
		StringBuffer xml = new StringBuffer();
		xml.append("<label>"+label+"</label>");
		xml.append("<index>"+index+"</index>");
		return xml;
	}
	
	

	/**
	 * delete a space
	 * @param runtimeData the ChannelRuntimeData object
	 */
	private void deleteSpace(ChannelRuntimeData runtimeData) {
		
		// if confirm
		String submit = runtimeData.getParameter("Submit");
		if (submit!=null) {
			
			String ind = runtimeData.getParameter("index_delete");
			int index = Integer.parseInt(ind);
			this.tempAdminServer.getSpaces().remove(index);
		}
		
	}
	
	
	
	/***************************************************************************/
	/**********************START OF CACHE FUNCTIONS*****************************/
	/***************************************************************************/

	/* (non-Javadoc)
	 * @see org.jasig.portal.ICacheable#generateKey()
	 */
	public ChannelCacheKey generateKey() {

	    ChannelCacheKey k = new ChannelCacheKey();
	    StringBuffer sbKey = new StringBuffer(1024);
	    sbKey.append(this.getClass().getName() + " : ");
	    sbKey.append("login : "+portalLogin+";");
	    sbKey.append("SubscribeId:"+this.staticData.getChannelSubscribeId());
	    k.setKeyScope(ChannelCacheKey.INSTANCE_KEY_SCOPE);

	    k.setKey(sbKey.toString());
	    k.setKeyValidity(new Long(System.currentTimeMillis()));
	    /*LogService.log(LogService.DEBUG,
	                              "CStockage::generateKey() (id : " +
	                              this.staticData.getChannelSubscribeId() +
	                              ") : generateKey :  -> Cle de cache:" + k.getKey());
	    */
		return k;
	}

	/* (non-Javadoc)
	 * @see org.jasig.portal.ICacheable#isCacheValid(java.lang.Object)
	 */
	public boolean isCacheValid(Object validity) {

	    boolean cacheValid = false;

	  if(runtimeData.getParameters().size()==0)
	  		cacheValid=true;

	  /*if (cacheValid) {
        LogService.log(LogService.DEBUG,
                                  "CStockage::isCacheValid (" +
                                  this.staticData.getChannelSubscribeId() +
                                  ") : isCacheValid -> YES");
      }
      else {
        LogService.log(LogService.DEBUG,
                                  "CStockage::isCacheValid (" +
                                  this.staticData.getChannelSubscribeId() +
                                  ") : isCacheValid -> NO");
      }*/
	    return cacheValid;
	}
	/***************************************************************************/
	/************************END OF CACHE FUNCTIONS*****************************/
	/***************************************************************************/
	
	
}
