/*
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.config;

import org.jasig.portal.ChannelStaticData;

import org.esupportail.portal.utils.CAS;
import org.esupportail.portal.utils.CASExceptions.*;

import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.esupportail.portal.channels.CStockage.channelAction.AbstractChannelAction;
import org.esupportail.portal.channels.CStockage.channelAction.BufferAction;
import org.esupportail.portal.channels.CStockage.channelAction.classic.sharing.SharedSpaceProperties;
import org.esupportail.portal.channels.CStockage.exception.ApplicationException;
import org.esupportail.portal.channels.CStockage.exception.BadConnexionParameters;
import org.esupportail.portal.channels.CStockage.exception.PropertiesException;
import org.esupportail.portal.channels.CStockage.exception.ServerException;
import org.esupportail.portal.channels.CStockage.exception.ChannelException;
import org.esupportail.portal.channels.CStockage.provider.access.ServerAccess;
import org.esupportail.portal.channels.CStockage.spacesPersonalization.DirectorySharingProperties;
import org.esupportail.portal.channels.CStockage.spacesPersonalization.target.UserForPersonalization;
import org.jasig.portal.security.IPerson;

/**
 * Id: Space.java,v 1.0 9 juil. 2004<br/>
 * Copyright (c) 2004 Esup Portail (www.esup-portail.org)<br/>
 * Classes: Space<br/>
 * Original Author: Yohan Colmant<br/>
 * This represents a file space on the server<br/>
 */
public class Space implements Comparable {


	/**
	 * Logger object
	 */
	protected static final Log log = LogFactory.getLog(Space.class);
	
	private ChannelStaticData staticData;
	
	/**
	 * The server object for this space
	 */
	private Server server;
	
	
	
	/**
	 * The space key
	 */
	private String key;
	
	/**
	 * The label of this space
	 */
	private String label;

	/**
	 * The path in the initial configuration file
	 */
	private String initialPathFromTheConfigurationFile;

	/**
	 * The regexp used to apply on the path
	 */
	private String pathRegexp;

	/**
	 * The separator used when the regexp is in few parts
	 */
	private String pathRegexpSeparator;

	/**
	 * The currentPath used
	 */
	private Vector currentPath = new Vector();
	
	/**
	 * The channel action type
	 */
	private String actionType;
	
	
	
	/**
	 * The class name used to manage the actions
	 */
	private String channelActionClass;		

	

	/**
	 * The namespace used for the metadata
	 */
	private String metadataNamespace;
	
	
	
	
	/**
	 * If the administrator allow users to share documents
	 */
	private String sharing;
	public static final String SHARING_SIMPLE = "simple";
	public static final String SHARING_COMPLEX = "complex";
	public static final String SHARING_NONE = "none";
	
	/**
	 * If the administrator allow users to set public documents in the sharing
	 */
	private String allowPublicSharing = "true";
	
	/**
	 * If we are obliged to see this space
	 */
	private String obliged = "true";
	
	/**
	 * If we show the quota in this space
	 */
	private String showQuota = "true";
	
	/**
	 * The attribute used to access the server
	 */
	private ServerAccess access;
	
	/**
	 * To manage the actions in funtion of the access class
	 */
	private AbstractChannelAction channelAction;
	
	
	
	
	/**
	 * The authorization list for this space
	 */
	private AuthorizationSpace authorizations;
	
	
	
	
	
	/**
	 * If this space is a personnal one
	 */
	private boolean personnalSpace = false;
	
	/**
	 * If this space is a personnal one
	 */
	private boolean fromConfigFile = true;
	
	
	
	/**
	 * The target for the sharing: the user key or the group key
	 */
	private SharedSpaceProperties currentViewer;
	

	/**
	 * The sharing directory properties of the current space
	 */
	private DirectorySharingProperties targetsOfSharing;
	
	/**
	 * The owner of the space
	 */
	private UserForPersonalization owner;
	
	/**
	 * If we set the acl into database
	 */
	private String setSharingIntoDatabase = "true";
	
	/**
	 * If the user can set ACL manually
	 */
	private String editOthersAcl = "false";
	
	
	/**
	 * The visibility of the browser url
	 */
	public static final String VISIBILITY_PUBLIC = "public_only";
	public static final String VISIBILITY_ACL = "acl_only";
	public static final String VISIBILITY_MENU = "menu";
	private String browserAccessUrlVisibility = VISIBILITY_PUBLIC;
	
	
	/**
	 * Used to manage the shibboleth users
	 */
	private String manageShibUsers = "false";
	
	
	public Space() {
	}
	
	
	public Space(String key) {
		this.key = key;
	}
	
	
	
	/**
	 * @param name the name of the parameter
	 * @return Returns the parameter.
	 */
	public String getParameter(String name) {
		return this.server.getParameter(name);
	}
	
	/**
	 * @return Returns the currentViewer.
	 */
	public SharedSpaceProperties getCurrentViewer() {
		return currentViewer;
	}
	/**
	 * @param currentViewer The targetOfsharing to set.
	 */
	public void setCurrentViewer(SharedSpaceProperties currentViewer) {
		this.currentViewer = currentViewer;
	}
	
	
	
	/**
	 * @return the setSharingIntoDatabase
	 */
	public String getSetSharingIntoDatabase() {
		return setSharingIntoDatabase;
	}


	/**
	 * @param setSharingIntoDatabase the setSharingIntoDatabase to set
	 */
	public void setSetSharingIntoDatabase(String setSharingIntoDatabase) {
		this.setSharingIntoDatabase = setSharingIntoDatabase;
	}

	
	
	
	
	/**
	 * @return the manageShibUsers
	 */
	public boolean isManageShibUsers() {
		return "true".equals(manageShibUsers);
	}


	/**
	 * @param manageShibUsers the manageShibUsers to set
	 */
	public void setManageShib(String manageShibUsers) {
		this.manageShibUsers = manageShibUsers;
	}


	/**
	 * @return the browserAccessUrlVisibility
	 */
	public String getBrowserAccessUrlVisibility() {
		return browserAccessUrlVisibility;
	}
	public boolean isBrowserAccessUrlVisibilityPublicOnly() {
		return VISIBILITY_PUBLIC.equals(browserAccessUrlVisibility);
	}
	public boolean isBrowserAccessUrlVisibilityAclOnly() {
		return VISIBILITY_ACL.equals(browserAccessUrlVisibility);
	}
	public boolean isBrowserAccessUrlVisibilityMenu() {
		return VISIBILITY_MENU.equals(browserAccessUrlVisibility);
	}


	/**
	 * @param browserAccessUrlVisibility the browserAccessUrlVisibility to set
	 */
	public void setBrowserAccessUrlVisibility(String browserAccessUrlVisibility) {
		this.browserAccessUrlVisibility = browserAccessUrlVisibility;
	}

	
	

	/**
	 * @return the editManualAcl
	 */
	public boolean isEditOthersAcl() {
		return "true".equals(editOthersAcl);
	}


	/**
	 * @param editManualAcl the editManualAcl to set
	 */
	public void setEditOther(String editOthersAcl) {
		this.editOthersAcl = editOthersAcl;
	}


	/**
	 * @return Returns the owner.
	 */
	public UserForPersonalization getOwner() {
		return owner;
	}
	/**
	 * @param owner The owner to set.
	 */
	public void setOwner(UserForPersonalization owner) {
		this.owner = owner;
	}
	
	
	/**
	 * Init the privileges of the current user. If he can read, write, write-acl ??
	 *
	 */
	public void initCurrentUserPrivileges() {
		
		String currentPath = getCurrentPath();
		//System.out.print("passe par initCurrentUserPrivileges: "+currentPath+" ");
		/*System.out.print("1: "+getCurrentViewer());
		System.out.print("2: "+getCurrentViewer().getUser());
		System.out.print("3: "+getCurrentViewer().getUser().getPersonalization());*/
		boolean[] userPrivileges = getServerAccessObject().checkPrivileges(currentPath);
		//System.out.println(userPrivileges[0]+" "+userPrivileges[1]+" "+userPrivileges[2]);
		if (userPrivileges[0]) {
			getCurrentViewer().getUser().getPersonalization().setReading(1);
		}
		else {
			getCurrentViewer().getUser().getPersonalization().setReading(0);
		}
		if (userPrivileges[1]) {
			getCurrentViewer().getUser().getPersonalization().setWriting(1);
		}
		else {
			getCurrentViewer().getUser().getPersonalization().setWriting(0);
		}
		if (userPrivileges[2]) {
			getCurrentViewer().getUser().getPersonalization().setSharing(1);
		}
		else {
			getCurrentViewer().getUser().getPersonalization().setSharing(0);
		}
	}
	
	
	/**
	 * @return Returns the targetsOfSharing.
	 */
	public DirectorySharingProperties getTargetsOfSharing() {
		return targetsOfSharing;
	}
	/**
	 * @param targetsOfSharing The targetsOfSharing to set.
	 */
	public void setTargetsOfSharing(DirectorySharingProperties targetsOfSharing) {
		this.targetsOfSharing = targetsOfSharing;
	}
	
	
	
	/**
	 * @return Returns the server.
	 */
	public Server getServer() {
		return server;
	}
	/**
	 * @param server The server to set.
	 */
	public void setServer(Server server) {
		this.server = server;
	}
	


	
	/**
	 * @return Returns the metadataNamespace.
	 */
	public String getMetadataNamespace() {
		return metadataNamespace;
	}
	/**
	 * @param metadataNamespace The metadataNamespace to set.
	 */
	public void setMetadataNamespace(String metadataNamespace) {
		this.metadataNamespace = metadataNamespace;
	}
	
	
	
	/**
	 * @return Returns the manageAcl.
	 */
	/*public boolean managesAcl() throws PropertiesException {		
		return server.managesAcl();
	}*/
	
	/**
	 * @param manageAcl The manageAcl to set.
	 */
	/*public void setManageAcl(String manageAcl) {
		if (manageAcl.equals("true"))
			this.manageAcl = true;
		else this.manageAcl = false;
	}*/
	
	
	/**
	 * return the authorization list
	 * @return the authorization list
	 */
	public AuthorizationSpace getAuthorizations() {			
		return authorizations;
	}

	/**
	 * add a new authorization to the list
	 * @param authorization the authorization to add
	 */
	public void setAuthorizations(AuthorizationSpace authorizations) {		
		this.authorizations = authorizations;
	}
	
	

	
	
	/**
	 * @return Returns the actionType.
	 */
	public String getActionType() {
		return actionType;
	}
	/**
	 * @param actionType The actionType to set.
	 */
	public void setActionType(String actionType) {
		this.actionType = actionType;
	}
	
	
	
	
	/**
	 * @return Returns the personnalSpace.
	 */
	public boolean isPersonnalSpace() {
		return personnalSpace;
	}
	/**
	 * @param personnalSpace The personnalSpace to set.
	 */
	public void setPersonnalSpace(boolean personnalSpace) {
		this.personnalSpace = personnalSpace;
	}
	
	
	
	

	/**
	 * @return the fromConfigFile
	 */
	public boolean isFromConfigFile() {
		return fromConfigFile;
	}

	/**
	 * @param fromConfigFile the fromConfigFile to set
	 */
	public void setFromConfigFile(boolean fromConfigFile) {
		this.fromConfigFile = fromConfigFile;
	}

	
	
	/**
	 * @return Returns the accessClass.
	 */
	public String getChannelActionClass() {
		return channelActionClass;
	}
	/**
	 * @param channelActionClass The channelActionClass to set.
	 */
	public void setChannelActionClass(String channelActionClass) {
		this.channelActionClass = channelActionClass;
	}
	
	
	
	/**
	 * @return Returns the key.
	 */
	public String getKey() {
		return key;
	}
	
	/**
	 * @param key The key to set.
	 */
	public void setKey(String key) {
		this.key = key;
	}
	
	/**
	 * @return Returns the label.
	 */
	public String getLabel() {
		return label;
	}
	
	/**
	 * @param label The label to set.
	 */
	public void setLabel(String label) {
		this.label = label;
	}
	
	
	
	
	
	/**
	 * @return Returns the pathRegexp.
	 */
	public String getPathRegexp() {
		return pathRegexp;
	}
	/**
	 * @param pathRegexp The pathRegexp to set.
	 */
	public void setPathRegexp(String pathRegexp) {
		this.pathRegexp = pathRegexp;
	}
	/**
	 * @return Returns the pathRegexpSeparator.
	 */
	public String getPathRegexpSeparator() {
		return pathRegexpSeparator;
	}
	/**
	 * @param pathRegexpSeparator The pathRegexpSeparator to set.
	 */
	public void setPathRegexpSeparator(String pathRegexpSeparator) {
		this.pathRegexpSeparator = pathRegexpSeparator;
	}
	
	
	
	/**
	 * @param path The path to set.
	 */
	public void setPath(String path) {
		
		this.initialPathFromTheConfigurationFile = path;
		
		// set the vector
		currentPath = initPath(path);
	}

	
	
	/**
	 * @param path The path to set.
	 */
	private Vector initPath(String path) {
		
		// set the vector
		Vector currentPath = new Vector();		
		
		String initPath = new String(path);		
		if (initPath.startsWith("/"))
			initPath = initPath.substring(1, initPath.length());		
		if (initPath.endsWith("/"))
			initPath = initPath.substring(0, initPath.length()-1);
				
		// we add it to the currentPath
		currentPath.addElement(initPath);	
		
		return currentPath;
	}
	
	
	
	public String getCurrentFullUrlPath() throws PropertiesException {
		String url = getServer().getUrl();	
		
		if (url.charAt(url.length()-1)!='/')
			url = url+"/";
		
		String path = getCurrentPath();
		//s+="\n       url:"+url;
		//s+="\n       path:"+path;
		if (!path.startsWith("/")) {
			url = url+path;
		}
		else {
			if (path.length()!=1)
				url = url+(path.substring(1, path.length()-1));
		}
		
		if (url.charAt(url.length()-1)!='/')
			url = url+"/";
		
		return url;
	}
	
	
	
	/**
	 * @return Returns the path.
	 */
	public String getCurrentPath() {	
		return getPath(currentPath);				
	}
	
	
	
	/**
	 * @return Returns the parent path until the space root
	 */
	public String getParentPathUntilSpaceRoot() {	
		int size = this.getPathSize();
		if (size == 1)
			return null;
		else
			return getParentPath(currentPath);				
	}
	
	/**
	 * @return Returns the space root path
	 */
	public String getSpaceRootPath() {	
		return (String)this.currentPath.elementAt(0);		
	}

	
	
	
	/**
	 * @return Returns the parent path.
	 */
	public String getParentPath() {	
		String path = getCurrentPath();
		String[] p = path.split("/");
		String s = "";
		
		// if we are at the root
		if (path.trim().equals("/")) {
			return null;
		}
		
		// if we are not at the root
		for (int i=0; i<p.length-1; i++) {
			s+=p[i]+"/";
		}
		
		return s;	
	}

	

	/**
	 * Get the path from an initial path, without first and last slashes
	 * @param path the path to transform
	 * @return the path without first and last slashes
	 */
	public static String getPathWithoutFirstAndLastSlash(String path) {
		String s = null;
		
		// if the path starts with "/"
		if (path.startsWith("/")) {
			s = path.substring(1);
		}
		else {
			s = path;
		}
		
		// if the path ends with "/"		
		if (s.endsWith("/")) {
			s = s.substring(0, s.length()-1);
		}
		
		return s;
	}
	
	
	
	/**
	 * @return Returns the path.
	 */
	public String getPath() {	
		return this.initialPathFromTheConfigurationFile;				
	}
	
	
	/**
	 * Return the path due to a current path vector
	 * @param currentPath
	 * @return the space current path
	 */
	private String getParentPath(Vector currentPath) {
		StringBuffer pathh = new StringBuffer("/"); 
		for (int i=0; i<currentPath.size()-1; i++) {
			String s = (String)currentPath.elementAt(i);
			if (!s.equals("")) {
				pathh.append(s);
				pathh.append("/");
			}			
		}
		
		return pathh.toString();	
	}
	
	/**
	 * Return the path due to a current path vector
	 * @param currentPath
	 * @return the space current path
	 */
	private String getPath(Vector currentPath) {
		StringBuffer pathh = new StringBuffer("/"); 
		for (int i=0; i<currentPath.size(); i++) {
			String s = (String)currentPath.elementAt(i);
			if (!s.equals("")) {
				pathh.append(s);
				pathh.append("/");
			}			
		}
		
		return pathh.toString();	
	}
	
	
	
	
	
	/**
	 * We check if the is a {...} form in the path. If yes, we replace by the real value
	 * @param person the connected person
	 */
	public void checkPath(IPerson person) {
		 
		String formLoginAttribute = "storageFormLogin";
		
		// if there are {} in the initial path, for each element between {}, we replace by the real value
		String path = "";
		String[] tab = initialPathFromTheConfigurationFile.split("\\{");
		for (int i=0; i<tab.length; i++) {
			String s = tab[i];
			int index = s.indexOf("}");
			
			// if there is a "}"
			if (index==-1) {
				path = path+s;
			}
			
			// there is no "}"
			else {
				String attributeName = s.substring(0, index);
				String endOfString = s.substring(index+1, s.length());
				
				// replace the attribute
				String value = "";
				if (attributeName.equals(formLoginAttribute)) {
					value = server.getLogin();
				}
				else {
					value = (String)person.getAttribute(attributeName);
				}
				
				// add the attribute value
				path = path+value;
				
				// add the end of the string
				path = path+endOfString;
			}
		}
		
		// we check if the path is a regular expression
		if (pathRegexp!=null) {
			
			String[] regexps = null;
			if (pathRegexpSeparator!=null) {
				regexps = pathRegexp.split(pathRegexpSeparator);
			}
			else {
				regexps = new String[1];
				regexps[0] = pathRegexp;
			}
			
			StringBuffer result = new StringBuffer();
			
 			for (int i = 0; i < regexps.length; i++) {
				
				Pattern p = Pattern.compile(regexps[i], Pattern.CASE_INSENSITIVE);
				Matcher m = p.matcher(path);
				
				result.append(m.replaceAll("$1"));				
			}
			
			path = result.toString();
			//pathRegexp = null;
			//pathRegexpSeparator = null;
		}
		
		// we fix the currentPath vector
		currentPath = initPath(path);		
		
		// log
		if (log.isDebugEnabled()) {
			log.debug("checkPath"+" :: currentPath = "+currentPath);
		}
 	}
	
	
	
	/**
	 * Delete the regexp
	 *
	 */
	public void clearRegexp() {
		pathRegexp = null;
		pathRegexpSeparator = null;
	}
	
	
	
	/**
	 * we look for a {...} form in the attribute. If yes, we replace it with the real value
	 * @param attributeName to check 
	 * @param person uPortal person object
	 */
	public void checkAttribute(String attributeName, IPerson person) {
		server.checkAttribute(attributeName, person);
	}
	
	
	
	/**
	 * Add a path element to the current directory
	 * @param pathElement
	 */
	public void addPathElement(String pathElement) {
		this.currentPath.add(pathElement);
	}
	
	/**
	 * Remove an element from the current path
	 * @param index
	 */
	public void removePathElement(int index) {
		this.currentPath.remove(index);
	}
	
	/**
	 * Return the path size
	 * @return the size
	 */
	public int getPathSize() {
		return currentPath.size();
	}
	
	
	/**
	 * Check if we are at the root of the space
	 * @return true if we are at the root, else false
	 */
	public boolean isCurrentPathAtRoot() {
		return getPathSize()==1;
	}
	
		
	/**
	 * Return the current element path at the good index
	 * @param index the selected index
	 * @return a string
	 */
	public String getPathElementAt(int index) {
		if (index == 0)
			return this.label;
		else return (String)this.currentPath.elementAt(index);
	}
		
	
	/**
	 * Check if we are authorized to read this space
	 * @param access the object used to access the server
	 * @return true if authorized else false
	 */
	public boolean canRead(ServerAccess access) {
		try {
			if (access.canRead(this.getCurrentPath()))
				return true;
			else return false;
		}
		catch(ChannelException e) {
			return false;
		}
	}		
	
	
	/**
	 * Set the server access object for this space
	 * @return true if we can access this space, else false
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws MalformedURLException
	 * @throws ApplicationException
	 * @throws PropertiesException
	 */
	public boolean setServerAccessObject() throws PropertiesException, ClassNotFoundException, InstantiationException, IllegalAccessException, MalformedURLException, ApplicationException{
		
		if (server.getServerAccessClass()==null) {
			log.error("setServerAccessObject :: "+getLabel()+" wrong server type for space "+getKey());
			return false;
		}
		
		// construct the object
		Class c = Class.forName(server.getServerAccessClass());
		access = (ServerAccess)c.newInstance();
		
		if (log.isDebugEnabled()) {
			log.debug("setServerAccessObject :: before access.init");
		}
		//System.out.println("avant init");
		access.init(this);
		if (log.isDebugEnabled()) {
			log.debug("setServerAccessObject :: after access.init");
		}
		//System.out.println("apres init");
		// add the current server hierarchy path
		//String serverCurrentHierPath = access.getServerCurrentHierPath();		
		//setPath(serverCurrentHierPath);
		
		
		// if the authentication is "asked", we don't try to connect
		if (server.isAskedAuthentication())
			return true;
		
		// try to connect
		try {
			//System.out.println("avant connect");
			if (log.isDebugEnabled()) {
				log.debug("setServerAccessObject :: before access.connect");
			}
			access.connect();			
			//System.out.println("apres connect");
			if (log.isDebugEnabled()) {
				log.debug("setServerAccessObject :: after access.connect");
			}
		}
		catch(ServerException e) {			
			//e.printStackTrace();
			// log
			if (log.isDebugEnabled()){
				log.debug("setServerAccessObject"+" :: "+getLabel()+" "+e);
			}
			
			return false;
		}
		catch(BadConnexionParameters e) {
			//e.printStackTrace();
			// log
			if (log.isDebugEnabled()){
				log.debug("setServerAccessObject"+" :: "+getLabel()+" "+e);
			}
			
			return false;
		}
		
		// if it is valid
		boolean valid = access.canRead(getCurrentPath());
		if (log.isDebugEnabled()) {
			log.debug("setServerAccessObject :: valid="+valid);
		}
		
		
		// disconnect
		try {
			access.disconnect();			
		}
		catch(ServerException e) {

			// log
			if (log.isDebugEnabled()){
				log.debug("setServerAccessObject"+" :: "+getLabel()+" "+e);
			}
			
		}
		
		return valid;
	}
	
	
	
	/**
	 * Return the object used to access the server
	 * @return the object used to access the server
	 */
	public ServerAccess getServerAccessObject() {
		return this.access;
	}
	
	
	
	/**
	 * init the server access object for this space
	 * @param person the uportal person object
	 * @throws MalformedURLException
	 * @throws PropertiesException
	 */
	public void initServerAccessObject(IPerson person) throws MalformedURLException, PropertiesException, IllegalAccessException, InstantiationException, ApplicationException, ClassNotFoundException {
		server.initServerAccessObjectForEachSpace(person);
	}
	
	
	
	
	
	/**
	 * Set the object used to manage the actions of the channel
	 * @param person the uPortal person object
	 * @param spaces the spaces used
	 * @param buffer the buffer used to get for example the clipboard
	 * @param userPortalLogin The user login in the portal
	 * @param userGroups The groups of the user in the portal
	 * @return true if well done
	 * @throws ChannelException
	 */
	public boolean setChannelActionObject(IPerson person, ArrayList spaces, BufferAction buffer, String userPortalLogin, Vector userGroups) throws PropertiesException, ApplicationException {
		
		try {
			
			if (this.channelActionClass==null)
				this.channelActionClass = "org.esupportail.portal.channels.CStockage.channelAction.classic.ChannelAction";				
			
			Class classe = Class.forName(this.channelActionClass);
			Object obj = classe.newInstance();
			
			this.channelAction = (AbstractChannelAction)obj;
			
			if (log.isDebugEnabled()) {
				log.debug("setChannelActionObject"+" :: before this.channelAction.init");
			}
			this.channelAction.init(person, this, spaces, buffer, userPortalLogin, userGroups);
			if (log.isDebugEnabled()) {
				log.debug("setChannelActionObject"+" :: after this.channelAction.init");
			}
		}
		catch(ClassNotFoundException e) {
			log.error("setChannelActionObject"+" :: "+e);			
			return false;
		}
		catch(IllegalAccessException e) {
			log.error("setChannelActionObject"+" :: "+e);	
			return false;
		}
		catch(InstantiationException e) {
			log.error("setChannelActionObject"+" :: "+e);	
			return false;
		}
		return true;
	}
	
	
	
	/**
	 * Get the channel action object
	 * @return the channel action object
	 */
	public AbstractChannelAction getChannelActionObject() {
		return this.channelAction;
	}
	
	
	
	

	
	/**
	 * @return check if the space allow the personalization
	 */
	public boolean managesAcl() throws PropertiesException {		

		// check if the server allows personalization
		if (server.managesAcl()) {
			return true;
		}
		else return false;
	}
	
	
	
	/**
	 * @return Returns the sharing.
	 */
	/*public boolean isSharing() throws PropertiesException {
		if (ChannelConfiguration.getInstance().isSpacesPersonalization()) {
			if (!personnalSpace) {
				
				// check if there are each aclxxx attribute and if type is webdav
				if (allowSharing !=null && allowSharing.equals("true")) {
					
					if (managesAcl()) {
						return true;
					}
					else return false;
					
				}
				else return false;
			}
			else {
				return currentViewer.isSharing();
			}
		}
		else {
			return false;
		}
	}*/
	public boolean allowsSharing() throws PropertiesException {
		
		// check if we have allowSharing="true"
		if (sharing !=null && (sharing.equals(SHARING_COMPLEX) || sharing.equals(SHARING_SIMPLE))) {
			
			// check if the server allows personalization
			if (server.allowsPersonalization()) {
				
				// check if the current user can write ACLs
				if (currentViewer!=null) {
					if (currentViewer.getUser().getPersonalization().getSharing()==1) {
						return true;
					}
				}
			}
		}
		return false;
	}
	
	
	public String getSharing() {
		if (sharing==null)
			return ""+SHARING_NONE;
		else return sharing;
	}
	

	/**
	 * @param sharing The allowsSharing to set.
	 */
	public void setSharing(String sharing) {
		if (sharing.equals("true")) {
			this.sharing = SHARING_SIMPLE;
		}
		else if (sharing.equals("false")) {
			this.sharing = SHARING_NONE;
		}
		else {
			this.sharing = sharing;
		}
	}
	
	
	
	
	/**
	 * @return the allowPublicSharing
	 */
	public boolean allowPublicSharing() {
		if (allowPublicSharing==null || !allowPublicSharing.equals("true"))
			return false;
		else return true;
	}


	/**
	 * @param allowPublicSharing the allowPublicSharing to set
	 */
	public void setAllowPublicSharing(String allowPublicSharing) {
		this.allowPublicSharing = allowPublicSharing;
	}


	/**
	 * @return Returns the obliged.
	 */
	public boolean isObliged() {
		if (obliged.equals("false")) {
			return false;
		}
		else return true;
	}

	/**
	 * @param obliged The obliged to set.
	 */
	public void setObligedSpace(String obligedSpace) {
		this.obliged = obligedSpace;
	}
	
	
	

	
	/**
	 * @return the showQuota
	 */
	public boolean showQuota() {
		if (showQuota.equals("false")) {
			return false;
		}
		else return true;
	}

	/**
	 * @param showQuota the showQuota to set
	 */
	public void setShowQuota(String showQuota) {
		this.showQuota = showQuota;
	}

	
	
	/**
	 * @return Returns the enableSharing.
	 */
	/*public String getEnableSharing() {
		return enableSharing;
	}*/
	
	
	
	
	

	/**
	 * Return a String representation of this space
	 */
	public String toString() {
		return 
		"key: "+key+"\n"+
		"label: "+label+"\n"+
		"path: "+getCurrentPath()+"\n";
	}
	
	
	
	
	/**
	 * Compare this to another object
	 * @param o object to compare
	 */
	public boolean equals(Object o) {
		//System.out.println("equals");
		Space s = (Space)o;
		/*
		boolean thisIsPersonal = this.isPersonnalSpace();
		boolean sIsPersonal = s.isPersonnalSpace();
		
		if(thisIsPersonal && sIsPersonal) {
			return this.getIdInDatabase().equals(s.getIdInDatabase());
		}
		else {		
			return this.key.equals(((Space)o).getKey());
		}*/
		if (this.key == null) {
			if (s.key==null) {
				return true;
			}
			else {
				return false;
			}
		}
		else {
			if (s.key==null) {
				return false;
			}
			else {
				return this.key.equals(s.getKey());
			}
		}
		
	}
	
	
	

	/**
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	public int compareTo(Object arg0) {
		
		try {
			Space comp = (Space)arg0;
			
			String thisPath = this.getCurrentFullUrlPath().toLowerCase();
			String compPath = comp.getCurrentFullUrlPath().toLowerCase();
			
			//System.out.println("compareTo "+thisPath+"  ...  "+compPath);
			
			if (thisPath==null || compPath==null)
				return -1;
			
			int compRes = thisPath.compareTo(compPath);
			if (compRes!=0)
				return compRes;
			else return -1;
		}
		catch(PropertiesException e) {
			log.error("compareTo"+" :: "+e);
			return 0;
		}
	}
	
	
	
	
	
	/**
	 * Clone this object
	 * @return a clone of this object
	 */
	public Object cloneWithoutServer() {
		Space clone = new Space();
		
		if (this.getOwner()!=null)
			clone.setOwner((UserForPersonalization)this.getOwner().clone());
		
		clone.key = this.key;
		clone.label = this.label;
	
		clone.actionType = this.actionType;
		clone.channelActionClass = this.channelActionClass;
		
		clone.sharing = this.sharing;
		clone.allowPublicSharing = this.allowPublicSharing;
		
		clone.obliged = this.obliged;
		clone.showQuota = this.showQuota;
		
		clone.initialPathFromTheConfigurationFile = this.initialPathFromTheConfigurationFile;
		clone.pathRegexp = this.pathRegexp;
		clone.pathRegexpSeparator = this.pathRegexpSeparator;
		
		clone.currentPath = (Vector)this.currentPath.clone();
		
		clone.metadataNamespace = this.metadataNamespace;
		
		if (this.authorizations!=null)
			clone.authorizations = (AuthorizationSpace)this.authorizations.clone();
		
		clone.personnalSpace = this.personnalSpace;
		clone.fromConfigFile = this.fromConfigFile;
		
		if (this.currentViewer!=null)
			clone.currentViewer = (SharedSpaceProperties)this.currentViewer.clone();
		
		if (this.targetsOfSharing != null)
			clone.targetsOfSharing = (DirectorySharingProperties)this.targetsOfSharing.clone();
		
		clone.setSharingIntoDatabase = this.setSharingIntoDatabase;
		clone.browserAccessUrlVisibility = this.browserAccessUrlVisibility;
		
		clone.editOthersAcl = this.editOthersAcl;
		clone.manageShibUsers = this.manageShibUsers;
		
		return clone;
	}
	

	
	/**
	 * Clone this object
	 * @return a clone of this object
	 */
	public Object clone() {
		Server originalServer = this.getServer();
		ArrayList originalSpaces = originalServer.getSpaces();
		
		int originalIndexOfThisInServer = -1;
		for (int i=0; originalIndexOfThisInServer==-1 && i<originalSpaces.size(); i++) {
			if (this==(Space)originalSpaces.get(i)) {
				originalIndexOfThisInServer = i;
			}
		}
		
		if (originalIndexOfThisInServer != -1) {
			Server clonedServer = (Server)originalServer.clone();
			Space clonedSpace = (Space)clonedServer.getSpaces().get(originalIndexOfThisInServer);
			
			return clonedSpace;
		}
		else {
			Server clonedServer = (Server)originalServer.clone();
			Space clonedSpace = (Space)cloneWithoutServer();
			clonedSpace.setServer(clonedServer);
			
			return clonedSpace;
		}
	}
	
	
	
	
	/**
	 * Get the xml in the configuration file style
	 * @return the xml in the configuration file style
	 */
	public StringBuffer getLocalXml() {
		

		StringBuffer xmlSpace = new StringBuffer();		
		xmlSpace.append("<SPACE");
	
		// key
		if (key!=null && !key.trim().equals("")) {
			xmlSpace.append(" key=\""+key+"\"\n");
		}
		
		// label
		if (label!=null && !label.trim().equals("")) {
			xmlSpace.append(" label=\""+label+"\"\n");
		}
		
		// path
		String path = getCurrentPath();
		if (path!=null && !path.trim().equals(""))
			xmlSpace.append(" path=\""+path+"\"\n");

		// pathRegexp
		if (pathRegexp!=null && !pathRegexp.trim().equals(""))
			xmlSpace.append(" pathRegexp=\""+pathRegexp+"\"\n");

		// pathRegexpSeparator
		if (pathRegexpSeparator!=null && !pathRegexpSeparator.trim().equals(""))
			xmlSpace.append(" pathRegexpSeparator=\""+pathRegexpSeparator+"\"\n");

		// actionType
		if (actionType!=null && !actionType.trim().equals(""))
			xmlSpace.append(" actionType=\""+actionType+"\"\n");

		// sharing
		if (sharing!=null && !sharing.trim().equals(""))
			xmlSpace.append(" sharing=\""+sharing+"\"\n");

		// allowPublicSharing
		if (allowPublicSharing!=null && !allowPublicSharing.trim().equals(""))
			xmlSpace.append(" allowPublicSharing=\""+allowPublicSharing+"\"\n");
		
		// obliged
		if (obliged!=null && !obliged.trim().equals(""))
			xmlSpace.append(" obliged=\""+obliged+"\"\n");

		// showQuota
		if (showQuota!=null && !showQuota.trim().equals(""))
			xmlSpace.append(" showQuota=\""+showQuota+"\"\n");

		// setSharingIntoDatabase
		if (setSharingIntoDatabase!=null && !setSharingIntoDatabase.trim().equals(""))
			xmlSpace.append(" setSharingIntoDatabase=\""+setSharingIntoDatabase+"\"\n");

		// browserAccessUrlVisibility
		if (browserAccessUrlVisibility!=null && !browserAccessUrlVisibility.trim().equals(""))
			xmlSpace.append(" browserAccessUrlVisibility=\""+browserAccessUrlVisibility+"\"\n");

		// editOthersAcl
		if (editOthersAcl!=null && !editOthersAcl.trim().equals(""))
			xmlSpace.append(" showOthersAcl=\""+editOthersAcl+"\"\n");

		// manageShibUsers
		if (manageShibUsers!=null && !manageShibUsers.trim().equals(""))
			xmlSpace.append(" manageShibUsers=\""+manageShibUsers+"\"\n");
		
		xmlSpace.append("/>\n");	
		
		return xmlSpace;
		
	}
	
	
	

	/**
	 * Get the xml in the configuration file style
	 * @return the xml in the configuration file style
	 */
	public String getXml() {
		
		StringBuffer xmlSpace = new StringBuffer();		
		
		xmlSpace.append(this.server.getLocalXmlBegin());
		
		xmlSpace.append(this.getLocalXml());
		
		xmlSpace.append(this.server.getLocalXmlEnd());
			
		return xmlSpace.toString();
		
	}

       /** 
       *  Get a proxy ticket from CAS for a space url
       *
       *  @param <b>String</b> space url to get a proxy ticket
       */
       public String getCasPt(String spaceUrl) {
               String casProxyTicket = null;

               try {
                       // Get a proxy ticket
                       casProxyTicket = CAS.get_pt(staticData, spaceUrl);
               }
               catch (CASPermException e) {
                       log.error("Space:GetCredential() : CASPermException : " + e.toString());
               }
               catch (CASTempException e) {
                       log.error("Space:GetCredential() : CASTempException : " + e.toString());
               }
               catch (CASGenericException e) {
                       log.error("Space:GetCredential() : CASGenericException : " + e.toString());
               }
               return casProxyTicket;
       }

       public void setStaticData(ChannelStaticData sd) {
               this.staticData = sd;
       }


	


}
