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


import java.net.MalformedURLException;
import java.util.Vector;

import org.esupportail.portal.channels.CStockage.exception.ApplicationException;
import org.esupportail.portal.channels.CStockage.exception.BadFormatException;
import org.esupportail.portal.channels.CStockage.exception.CancelException;
import org.esupportail.portal.channels.CStockage.exception.CreateDirectoryException;
import org.esupportail.portal.channels.CStockage.exception.BadConnexionParameters;
import org.esupportail.portal.channels.CStockage.exception.NoneSelectedResourceException;
import org.esupportail.portal.channels.CStockage.exception.NotAuthorizedException;
import org.esupportail.portal.channels.CStockage.exception.NotAuthorizedNewDirException;
import org.esupportail.portal.channels.CStockage.exception.NotEmptyDirectoryException;
import org.esupportail.portal.channels.CStockage.exception.NotExistsResourceException;
import org.esupportail.portal.channels.CStockage.exception.PasteDeletedResourceException;
import org.esupportail.portal.channels.CStockage.exception.PropertiesException;
import org.esupportail.portal.channels.CStockage.exception.ServerException;
import org.esupportail.portal.channels.CStockage.exception.StillExistsException;
import org.esupportail.portal.channels.CStockage.exception.TooMuchSelectedException;
import org.esupportail.portal.channels.CStockage.exception.ChannelException;
import org.esupportail.portal.channels.CStockage.channelAction.AbstractChannelAction;
import org.esupportail.portal.channels.CStockage.channelAction.Constants;
import org.esupportail.portal.channels.CStockage.channelAction.classic.DefaultRenderXml;
import org.esupportail.portal.channels.CStockage.config.Space;
import org.jasig.portal.ChannelRuntimeData;
import org.jasig.portal.ChannelStaticData;
import org.jasig.portal.MultipartDataSource;
import org.jasig.portal.PortalException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.portal.utils.XSLT;
import org.xml.sax.ContentHandler;

/**
 * Id: ChannelAction.java,v 1.0 24 sept. 2004
 * Copyright (c) 2004 Esup Portail (www.esup-portail.org)
 * Classes: ChannelAction
 * Original Author: Yohan Colmant
 * Class used to manage the actions when we are in a classic space context
 */
public class ChannelAction extends AbstractChannelAction {


	/**
	 * Logger object
	 */
	protected static final Log log = LogFactory.getLog(ChannelAction.class);
	
	
	/**
	 * The stylesheet used
	 */
	private String stylesheet;
	
	
	/**
	 * Default constructor
	 */
	public ChannelAction() {
		
	}
	
	
	
	
	/**
	 * Manage the actions when refreshing the channel
	 * @param staticData the static data channel object
	 * @param runtimeData the runtime data channel object
	 * @param out a sax document handler
	 * @param xslt the xslt motor object
	 * @param setStaticDataException the excpetion throwed in the setStaticData method
	 * @throws PortalException
	 */
	public void checkCalledAction(ChannelStaticData staticData, ChannelRuntimeData runtimeData, ContentHandler out, XSLT xslt, ChannelException setStaticDataException) throws PortalException {		
		
		// the string we will return
		StringBuffer xml = new StringBuffer();
		xml.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");		
		xml.append("<ROOT>");
		
		// set the mod
		// in the channel, there are 2 action menus. 
		// those menus have the same name modeDav. 
		// To differentiate the menu that we have selected, we check the value of the both. 
		// the menu with a not null value is the one we have selected.  
		String currentMode = null;
		String[] mod=runtimeData.getParameterValues("modeDav");
		if (mod != null){
			for (int i = 0; i<mod.length;i++){
				if (!mod[i].equals("")) {
					currentMode = mod[i];
				}
			}
		}
				
		// the stylesheet we are going to use
		stylesheet = "";

		// log
		if (log.isDebugEnabled()){
			log.debug("checkCalledAction"+" :: currentMode = "+currentMode);
		}
		
		// Xml string generated by the diferents methods
		StringBuffer xmlTemp = new StringBuffer();
		
		try {						
			
			// if password set
			try {				
				if (currentMode!=null && currentMode.equals(Constants.PASSWORD_MODE)) {
					String login = runtimeData.getParameter("login");
					String password = runtimeData.getParameter("password");
					this.currentSpace.setLogin(login);
					this.currentSpace.setPassword(password);
					this.currentSpace.getServerAccessObject().init(this.currentSpace);
					currentMode = Constants.SHOW_CURRENT_DIR_MODE;
				}
			}
			catch(MalformedURLException e) {							
				if (log.isDebugEnabled()){
					log.debug("checkCalledAction"+" :: "+e);
				}
				throw new PropertiesException();
			}		
			
			
			// if none staticdata exception
			if (setStaticDataException==null) {
				
				// if it the asked authentication, and none password still set
				if (this.currentSpace.isAskedAuthentication() && this.currentSpace.getPassword()==null) {
					throw new BadConnexionParameters();
				}
				
				// else, connect to the server
				else {
					try {					
						this.currentSpace.getServerAccessObject().connect();
					}
					catch(BadConnexionParameters e) {
						throw e;
					}
					catch(Exception e) {
						setStaticDataException= new ServerException();
					}
				}
			}
			
			// check the setStaticDataException
			if (setStaticDataException!=null) {

				// log
				if (log.isDebugEnabled()){
					log.debug("checkCalledAction"+" :: setStaticDataException = "+setStaticDataException);
				}
				
				throw setStaticDataException;
			}
			
			
			// set the default mod
			if (currentMode == null) {			
				currentMode = Constants.SHOW_CURRENT_DIR_MODE;
			}

			//////////////////////////////////////////////////////
			// D I R E C T O R Y
			//Display the current directory
			if (currentMode.equals(Constants.SHOW_CURRENT_DIR_MODE)) {	
				xmlTemp = renderXmlShowCurrentDir(runtimeData);			
				stylesheet = "CStockage";
			}
			//Go to the parent directory
			else if (currentMode.equals(Constants.DIRECTORY_BACK)) {	
				directoryBack();
				xmlTemp = renderXmlShowCurrentDir(runtimeData);			
				stylesheet = "CStockage";
			}
			//prepare create
			else if (currentMode.equals(Constants.SET_NAME_FOR_CREATE_DIR_MODE)) {		
				stylesheet = "setNewDirectory";						
			}
			//Real create
			else if (currentMode.equals(Constants.CREATE_DIR_MODE)) {		
				stylesheet = "CStockage";
				createDir(runtimeData);		
				xmlTemp = DefaultRenderXml.getXml(spaces, currentSpace, null, "2004", config);
			}

			//////////////////////////////////////////////////////
			// U P L O A D
			//prepare
			else if (currentMode.equals(Constants.SET_FILE_TO_UPLOAD_MODE)) {										
				stylesheet = "setUpload";
			} 
			//Real upload
			else if (currentMode.equals(Constants.UPLOAD_MODE)) {
				upload(runtimeData);
				stylesheet = "CStockage";
				xmlTemp = DefaultRenderXml.getXml(spaces, currentSpace, null, "2001", config);
			} 


			//////////////////////////////////////////////////////
			//D E L E T E
			//confirm
			else if (currentMode.equals(Constants.CONFIRM_DELETE_MODE)) {					
				StringBuffer x = renderXmlConfirmDelete(runtimeData);
				//
				if (config.getConfirmDel()) {
					stylesheet = "confirmDelete";
					xmlTemp = x;
				}
				
				// sinon, on passe directement au mode supprimer
				else {
					deleteWithoutConfirm();
					stylesheet = "CStockage";
					xmlTemp = DefaultRenderXml.getXml(spaces, currentSpace, null, "2002", config);
				}													
			}
			//Real delete
			else if (currentMode.equals(Constants.DELETE_MODE)) {										
				delete(runtimeData);
				stylesheet = "CStockage";			
				xmlTemp = DefaultRenderXml.getXml(spaces, currentSpace, null, "2002", config);
			}

			//////////////////////////////////////////////////////  
			//C O P Y
			//set clipboard
			else if (currentMode.equals(Constants.SET_CLIPBOARD_FOR_COPY_MODE)) {			
				stylesheet = "CStockage";				
				setClipboard(Constants.COPY_MODE, runtimeData);
				xmlTemp = DefaultRenderXml.getXml(spaces, currentSpace, null, "2007", config);
			}
			
			// ask if we paste really
			else if (currentMode.equals(Constants.CONFIRM_PASTE_MODE)) {			
				stylesheet = "confirmPaste";								
				xmlTemp = renderXmlConfirmPaste();
			}
			
			//Real paste
			else if (currentMode.equals(Constants.PASTE_MODE)) {
				stylesheet = "CStockage";
				xmlTemp = paste(runtimeData);						
			}

			//////////////////////////////////////////////////////
			//M O V E
			//set clipboard
			else if (currentMode.equals(Constants.SET_CLIPBOARD_FOR_MOVE_MODE)) {			
				stylesheet = "CStockage";
				setClipboard(Constants.MOVE_MODE, runtimeData);
				xmlTemp = DefaultRenderXml.getXml(spaces, currentSpace, null, "2007", config);
			}			

			//////////////////////////////////////////////////////
			//R E N A M E
			//prepare
			else if (currentMode.equals(Constants.SET_NAME_FOR_RENAME_MODE)) {
				stylesheet = "setRename";
				xmlTemp = renderXmlSetNameForRename(runtimeData);		
			}
			//Real rename
			else if (currentMode.equals(Constants.RENAME_MODE)) {				
				rename(runtimeData);
				stylesheet = "CStockage";	
				xmlTemp = DefaultRenderXml.getXml(spaces, currentSpace, null, "2003", config);
			} 
			
			xml.append(xmlTemp);			
				
		}		
		catch(BadConnexionParameters e) {
			stylesheet = "CStockage";
			xml.append(DefaultRenderXml.getXmlForPasswordSetting(spaces, currentSpace, e, config));
			// log
			if (log.isDebugEnabled()){
				log.debug("checkCalledAction"+" :: "+e);
			}
		}
		catch(ChannelException e) {
			stylesheet = "CStockage";
			xml.append(DefaultRenderXml.getXml(spaces, currentSpace, e, null, config));
			// log
			if (log.isDebugEnabled()){
				log.debug("checkCalledAction"+" :: "+e);
			}
		}
		
		try {
			// discconnect from the dav
			this.currentSpace.getServerAccessObject().disconnect();
		}
		catch (Exception e) {			
			// log
			if (log.isDebugEnabled()){
				log.debug("checkCalledAction"+" :: "+e);
			}
		}
				
		
		// set the stylesheet and the parameters

		//specify the stylesheet selector		
		xslt.setXSL("CStockage.ssl", stylesheet, runtimeData.getBrowserInfo());
		
		
		//url to the channel
		xslt.setStylesheetParameter("baseActionURL",runtimeData.getBaseActionURL());
		//url to the download worker
		xslt.setStylesheetParameter( "downloadURL",runtimeData.getBaseWorkerURL( org.jasig.portal.UPFileSpec.FILE_DOWNLOAD_WORKER,true).replaceAll("%2F","/"));				
		
		
		// the parameter to know if there is a resource in the clipboard
		if (buffer.getClipboard() != null)
			xslt.setStylesheetParameter("isClipboardEmpty","false");			      
		
		// the parameter used in the copy/move mode. tell if the mode is copy or move
		String clipboardParameter = buffer.getClipboardParameter();
		if (clipboardParameter != null) {
			xslt.setStylesheetParameter("clipboardParameter",clipboardParameter);			

		}
		
		// the final balise
		xml.append("</ROOT>");
		//System.out.println(xml);
		//pass the result XML to the styling engine.
		xslt.setXML(xml.toString());			

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

	
	/**
	 * Generate the XML String for this mod
	 * @param runtimeData the runtime data channel object
	 * @return the XML for this mod
	 */
	private StringBuffer renderXmlShowCurrentDir(ChannelRuntimeData runtimeData) {	
		//When we enter in a sub directory ...		
		String directoryCible = runtimeData.getParameter("targetDirectory");
		if (directoryCible != null) {

			//System.out.println("targetDirectory: "+directoryCible); 
			
			// log
			if (log.isDebugEnabled()){
				log.debug("renderXmlShowCurrentDir"+" :: directoryCible = "+directoryCible);
			}

			return DefaultRenderXml.getXml(spaces, currentSpace, directoryCible, null , null, config);
		}
		else {
			//... by naviguation tool
			String dir = runtimeData.getParameter("link");
			if (dir != null) {

				// log
				if (log.isDebugEnabled()){
					log.debug("renderXmlShowCurrentDir"+" :: link = "+dir);
				}
				
				int index = Integer.parseInt(dir);
				int curentDirLength = currentSpace.getPathSize();
				if (index < curentDirLength) {					
					for (int i=0; i< (curentDirLength-(index+1)); i++) {						
						currentSpace.removePathElement(currentSpace.getPathSize()-1);
					}			
				}
				return DefaultRenderXml.getXml(spaces, currentSpace, null , null, config);
			}
		}
		
		// all others cases
		return DefaultRenderXml.getXml(spaces, currentSpace, null , null, config);
	}
	
	
	/**
	 * Go to the parent directory
	 */
	private void directoryBack() {

		// log
		if (log.isDebugEnabled()){
			log.debug("directoryBack");
		}

		if (currentSpace.getPathSize()>1)
			currentSpace.removePathElement(currentSpace.getPathSize()-1);		
	}
	
	
	
 

	/**
	 * Create a new directory
	 * @param runtimeData the runtime data channel object
	 */
	private void createDir(ChannelRuntimeData runtimeData) throws CancelException, ApplicationException, CreateDirectoryException, StillExistsException, BadFormatException, NotAuthorizedException, NotAuthorizedNewDirException, NotExistsResourceException{
		String submit = runtimeData.getParameter("Submit");
		String cancel = runtimeData.getParameter("Cancel");
		
		if (submit == null) {
			throw new CancelException();
		} 
		else {
			String information = null;
			String error = null;
				
			String path = currentSpace.getPath();
			int errorCode = 0;

			String newDirName = runtimeData.getParameter("new_dir");
			this.currentSpace.getServerAccessObject().createDir(newDirName, path);
        	

			// log
			if (log.isDebugEnabled()){
				log.debug("createDir"+" :: newDirName = "+newDirName);
			}

			
		}
	}

	
	
	
	


	/**************************
	 *   Rename/Delete methods
	 **************************/
		
	
	
	
	/**
	 * Generate the XML String for this mod
	 * @param runtimeData the runtime data channel object
	 * @return the XML StringBuffer for this mod
	 * @throws ChannelException
	 */
	private StringBuffer renderXmlSetNameForRename(ChannelRuntimeData runtimeData) throws ChannelException {
		// we get the files we want to rename
		String[] files = runtimeData.getParameterValues("listeFic");
		
		if (files == null) {

			// log
			if (log.isDebugEnabled()){
				log.debug("renderXmlSetNameForRename"+" :: NoneSelectedResourceException");
			}

			stylesheet = "CStockage";
			throw new NoneSelectedResourceException();
		}		
		else {						
			// if there is more than one file
			if (files.length > 1) {

				// log
				if (log.isDebugEnabled()){
					log.debug("renderXmlSetNameForRename"+" :: TooMuchSelectedException");
				}
				
				stylesheet = "CStockage";
				throw new TooMuchSelectedException();
			}
			else {			
				String fileToRename = files[0];				

				// System.out.println("fileToRename: "+fileToRename);  
				
				// log
				if (log.isDebugEnabled()){
					log.debug("renderXmlSetNameForRename"+" :: fileToRename = "+fileToRename);
				}
				
				buffer.setFileToRename(fileToRename);
				StringBuffer sb = new StringBuffer();
				sb.append("<OLD>");
				fileToRename = fileToRename.replaceAll("&","&amp;");
				fileToRename = fileToRename.replaceAll("\"","&#148;");
				sb.append(fileToRename);
				sb.append("</OLD>");
				return sb;
			}					
		}
	}
	
	
	/**
	 * Rename the selected resource
	 * @param runtimeData the runtime data channel object
	 */
	private void rename(ChannelRuntimeData runtimeData) throws ChannelException{
		String submit = runtimeData.getParameter("Submit");
		String cancel = runtimeData.getParameter("Cancel");
		
		if (submit == null) {
			buffer.setFileToRename(null);
			throw new CancelException();
		}
		else {
			String information = null;
			String error = null;
				
			// we clicked on the validate button: we rename 
			String path = currentSpace.getPath();		
						
			String newName = runtimeData.getParameter("new_name");
			
			// log
			if (log.isDebugEnabled()){
				log.debug("rename"+" :: newName = "+newName);
			}
			
			this.currentSpace.getServerAccessObject().rename(buffer.getFileToRename(), newName, path);
			
			buffer.setFileToRename(null);						
		}
	}
		
	
	
	
	
	
	/**
	 * Generate the XML String for this mod
	 * @param runtimeData the runtime data channel object
	 * @return the xml used to confirm a delete
	 * @throws ChannelException
	 */
	private StringBuffer renderXmlConfirmDelete(ChannelRuntimeData runtimeData) throws ChannelException {
		// Xml generated
		StringBuffer xml = new StringBuffer();
		
		String[] filesToDelete = runtimeData.getParameterValues("listeFic");
		buffer.setFilesToDelete(filesToDelete);	
		if (filesToDelete == null) {

			// log
			if (log.isDebugEnabled()){
				log.debug("renderXmlConfirmDelete"+" :: NoneSelectedResourceException");
			}

			throw new NoneSelectedResourceException();			
		}
		
		else {
			//check if it is allowed to delete non empty directory
			boolean authorise = config.getAllowDelNonEmptyFolder();		

			//For each piece of the selection
			for (int j=0;j<filesToDelete.length;j++){
				String fileName = filesToDelete[j];				

				String path = currentSpace.getPath();			
				
				//check if it is a directory or a file
				boolean isDirectory = this.currentSpace.getServerAccessObject().isDirectory(fileName, path);																
				if (isDirectory) {	
					
					//check if non empty
					boolean empty = this.currentSpace.getServerAccessObject().isEmpty(fileName, path);														
										
					if (!empty && !authorise) {
						//Delete forbidden for this directory
						buffer.setFilesToDelete(null);						
						throw new NotEmptyDirectoryException();
					}
					else if (!empty && authorise) {
						fileName = fileName.replaceAll("&","&amp;");
						fileName = fileName.replaceAll("\"","&#148;");
						xml.append("<DIR name=\""+fileName+"\" empty=\""+false+"\"/>");
					}
					else if (empty) {			
						fileName = fileName.replaceAll("&","&amp;");
						fileName = fileName.replaceAll("\"","&#148;");
						xml.append("<DIR name=\""+fileName+"\" empty=\""+true+"\"/>");
					}
				}
				
				else if (!isDirectory) {	
					fileName = fileName.replaceAll("&","&amp;");
					fileName = fileName.replaceAll("\"","&#148;");
					xml.append("<FILE name=\""+fileName+"\"/>");
				}
			}			
			return xml;					
		}
	}
	
		
	
	
	
	/**
	 * Delete the specified resource(s)
	 * @param runtimeData the runtime data channel object
	 * @throws ChannelException
	 */
	private void delete(ChannelRuntimeData runtimeData) throws ChannelException  {
		String submit = runtimeData.getParameter("Submit");
		String cancel = runtimeData.getParameter("Cancel");
		
		if (submit == null) {
			throw new CancelException();
		}
		
		String information = null;
		String error = null;
			
		String path = currentSpace.getPath();	
		
		String[] filesToDelete = buffer.getFilesToDelete();
		
		for (int i=0; i<filesToDelete.length; i++) {
			String file = (String)filesToDelete[i];

			// log
			if (log.isDebugEnabled()){
				log.debug("delete"+" :: file = "+file);
			}

			this.currentSpace.getServerAccessObject().delete(file, path);				
		}
			
		buffer.setFilesToDelete(null);								
	} 
	
	
	/**
	 * Delete resource(s) without confirmation
	 * @throws ChannelException
	 */
	private void deleteWithoutConfirm() throws ChannelException {		
		
		String information = null;
		String error = null;
			
		String path = currentSpace.getPath();		
		
		String[] filesToDelete = buffer.getFilesToDelete();
		
		for (int i=0; i<filesToDelete.length; i++) {
			String file = (String)filesToDelete[i];

			// log
			if (log.isDebugEnabled()){
				log.debug("deleteWithoutConfirm"+" :: file = "+file);
			}
			
			this.currentSpace.getServerAccessObject().delete(file, path);				
		}
			
		buffer.setFilesToDelete(null);									
	}
	
	
	
	
	/**
	 * Start the upload
	 * @param runtimeData the runtime data channel object
	 * @throws ChannelException
	 */
	private void upload(ChannelRuntimeData runtimeData) throws ChannelException {
	       
		String submit = runtimeData.getParameter("Submit");
		String cancel = runtimeData.getParameter("Cancel");
		Object inputFile = runtimeData.getObjectParameter("input_file");        
	
		if (submit == null) {		
			throw new CancelException();		       		       	
		}
		else {			
			// if file is null
			if (inputFile == null) {	
				// log
				if (log.isDebugEnabled()){
					log.debug("upload"+" :: NotExistsResourceException");
				}
				
				throw new NotExistsResourceException();
			}			
			
			String information = null;
			String error = null;
			
			// get a reference to the file
			MultipartDataSource mps = (MultipartDataSource)inputFile;   	        	
			
	        String path = currentSpace.getPath();

			// log
			if (log.isDebugEnabled()){
				log.debug("upload"+" :: inputFile = "+mps.getName());
			}
			
	        this.currentSpace.getServerAccessObject().upload(mps, path);
		}
	}


	
	
	/**
	 * Set the clipboard
	 * @param mode used: copy or move
	 * @param runtimeData the runtime data channel object
	 * @throws NoneSelectedResourceException
	 * @throws ApplicationException
	 * @throws NotAuthorizedException
	 */
	private void setClipboard(String mode, ChannelRuntimeData runtimeData) throws NoneSelectedResourceException, ApplicationException, NotAuthorizedException {			
		
		//check the files/directories from parameters
		String[] files = runtimeData.getParameterValues("listeFic");
		if (files == null) {

			// log
			if (log.isDebugEnabled()){
				log.debug("setClipboard"+" NoneSelectedResourceException");
			}

			throw new NoneSelectedResourceException();
		}		
		else {
			
			// we check if we are authorized to copy all selected resources			
			String tempPath = currentSpace.getPath();
			for (int j=0;j<files.length;j++){
				String fileName = files[j];
				if (!this.currentSpace.getServerAccessObject().canRead(fileName, tempPath)) {

					// log
					if (log.isDebugEnabled()){
						log.debug("setClipboard"+" :: fileName = "+fileName+" : NotAuthorizedException");
					}

					// we erase the clipboard					
					buffer.setClipboard(null);
					buffer.setClipboardParameter(null);
					buffer.setClipboardPath(null);
					buffer.setClipboardSpace(null);
					
					// we throw an exception
					throw new NotAuthorizedException();
				}
			}
			
			// if none NotAuthorizedException throwed
			
			// files/directories to copy			
			buffer.setClipboard(new Vector());
			buffer.setClipboardPath(currentSpace.getPath());
			buffer.setClipboardSpace(currentSpace);
			
			for (int j=0;j<files.length;j++){
				String fileName = files[j];

				// log
				if (log.isDebugEnabled()){
					log.debug("setClipboard"+" :: add "+fileName+" into the clipboard");
				}
				
				buffer.getClipboard().addElement(fileName);				
			}			
		}
		

		// log
		if (log.isDebugEnabled()){
			log.debug("setClipboard"+" :: setClipboardParameter("+mode+")");
		}
		
		buffer.setClipboardParameter(mode);
	}
	
	
	
	/**
	 * Generate the XML String for this mod
	 * @return the XML String for this mod
	 * @throws ChannelException
	 */
	private StringBuffer renderXmlConfirmPaste() throws ChannelException {
		
		// we check if we can paste here
		try {
			
			// log
			if (log.isDebugEnabled()){
				log.debug("renderXmlConfirmPaste"+" :: canPaste "+buffer.getClipboard()+" ?");
			}
			
			this.currentSpace.getServerAccessObject().canPaste(buffer.getClipboardSpace(), this.currentSpace.getKey(), buffer.getClipboardPath(), buffer.getClipboard(), currentSpace.getPath());
		}
		catch (PasteDeletedResourceException e) {
			buffer.setClipboard(null);
			buffer.setClipboardParameter(null);
			buffer.setClipboardPath(null);
			buffer.setClipboardSpace(null);
			
			throw new PasteDeletedResourceException();
		}
		
		// Xml generated
		StringBuffer xml = new StringBuffer();
		
		//For each piece of the selection
		Vector clipboard = buffer.getClipboard();
		for (int j=0;j<clipboard.size();j++){
			String fileName = (String)clipboard.elementAt(j);				
			
			//check if it is a directory or a file
			boolean isDirectory = buffer.getClipboardSpace().getServerAccessObject().isDirectory(fileName, buffer.getClipboardPath());								
						
			if (isDirectory) {	
					
				//check if non empty
				boolean empty = buffer.getClipboardSpace().getServerAccessObject().isEmpty(fileName, buffer.getClipboardPath());														
				
				if (!empty) {
					fileName = fileName.replaceAll("&","&amp;");
					fileName = fileName.replaceAll("\"","&#148;");
					xml.append("<DIR name=\""+fileName+"\" empty=\""+false+"\"/>");
				}
				else if (empty) {
					fileName = fileName.replaceAll("&","&amp;");
					fileName = fileName.replaceAll("\"","&#148;");
					xml.append("<DIR name=\""+fileName+"\" empty=\""+true+"\"/>");
				}
			}				
			else if (!isDirectory) {					
				fileName = fileName.replaceAll("&","&amp;");
				fileName = fileName.replaceAll("\"","&#148;");
				xml.append("<FILE name=\""+fileName+"\"/>");
			}
		}
			
		return xml;							
	}
	
	
	/**
	 * Generate the XML String for this mod
	 * @param runtimeData the runtime data channel object
	 * @return the XML String for this mod
	 * @throws ChannelException
	 */
	private StringBuffer paste(ChannelRuntimeData runtimeData) throws ChannelException {
		String submit = runtimeData.getParameter("Submit");
		String cancel = runtimeData.getParameter("Cancel");
		
		Vector clipboard = buffer.getClipboard();
		String clipboardPath = buffer.getClipboardPath();
		String clipboardParameter = buffer.getClipboardParameter();
		Space clipboardSpace = buffer.getClipboardSpace();
		
		if (cancel == null) {			
			for (int i=0; i<clipboard.size(); i++) {		
				String clipboardElement = ((String)clipboard.elementAt(i));
				
				if (clipboardParameter.equals(Constants.COPY_MODE)) {
					
					// log
					if (log.isDebugEnabled()){
						log.debug("paste"+" :: copy clipboardElement = "+clipboardElement);
					}

					this.currentSpace.getServerAccessObject().copy(clipboardElement, clipboardSpace, clipboardPath, currentSpace.getKey(), currentSpace.getPath());
				}
				else {
					
					// log
					if (log.isDebugEnabled()){
						log.debug("paste"+" :: move clipboardElement = "+clipboardElement);
					}
					
					this.currentSpace.getServerAccessObject().move(clipboardElement, clipboardSpace, clipboardPath, currentSpace.getKey(), currentSpace.getPath());
				}						
			}			
		} 		
		else {

			// log
			if (log.isDebugEnabled()){
				log.debug("paste"+" :: CancelException");
			}

			throw new CancelException();
		}				
		
		// if well done
		if (clipboardParameter.equals(Constants.COPY_MODE)) {			
			/*
			// if we want to set empty the clipboard
			clipboard = null;
			clipboardParameter = null;
			clipboardPath = null;
			*/
			return DefaultRenderXml.getXml(spaces, currentSpace, null, "2005", config);	
		}
		else {
			buffer.setClipboard(null);
			buffer.setClipboardParameter(null);
			buffer.setClipboardPath(null);
			buffer.setClipboardSpace(null);
			return DefaultRenderXml.getXml(spaces, currentSpace, null, "2006", config);	
		}
	}
	
	
	
	
	
}
