 /*
 * ====================================================================
 *
 * Copyright 2004 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.apache.slide.event;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.servlet.http.HttpServletRequest;

import org.apache.slide.common.Domain;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.SlideToken;
import org.apache.slide.content.Content;
import org.apache.slide.content.InsufficientStorageException;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionDescriptors;
import org.apache.slide.content.RevisionDescriptorNotFoundException;
import org.apache.slide.content.RevisionNotFoundException;
import org.apache.slide.lock.ObjectLockedException;
import org.apache.slide.security.AccessDeniedException;
import org.apache.slide.structure.LinkedObjectNotFoundException;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.util.conf.Configurable;
import org.apache.slide.util.conf.Configuration;
import org.apache.slide.util.conf.ConfigurationException;
import org.apache.slide.util.logger.Logger;
import org.apache.slide.webdav.event.DetailedWebdavEvent;
import org.apache.slide.webdav.event.WebdavAdapter;
import org.apache.slide.webdav.event.WebdavEvent;
import org.apache.slide.webdav.method.AbstractWebdavMethod;
import org.apache.slide.webdav.method.PutMethod;
import org.apache.slide.webdav.util.WebdavUtils;

/**
 * 
 * @author tbellemb
 * @version 1.1.0-RC1
 * 
 * The QuotaListener class manages quota on the server.
 * @link http://esup-portail.org/consortium/espace/Stockage_2F/serveur/documents/specifications/specifWebDAVQuotas.html
 * 
 * Modifications : 
 * 2005.07.12 : Exporting the QuotaElement class and constants
 *  
 */

public class QuotaListener extends WebdavAdapter implements ContentListener, Configurable {

	// logger
	private static final String LOG_CHANNEL = "org.apache.slide.event.QuotaListener";

	// path on which quota are applied
	private static String quotaPath;
	
	// it is required to save the content length of a resource to be deleted to update the resource quota MD
	// after the deletion - an hashtable does the job
	private Hashtable tableOfResourceLength = new Hashtable();

	// objects stored in the hashtable below
	// we use Object to take advantage of the garbage collector
	private class ResourceLengthElement {
		
		private String uri;
		private String contentLength;
		
		public ResourceLengthElement (String uri, long contentLength) {
			this.uri = uri;
			this.contentLength = String.valueOf((int)contentLength);
			
		}// resourceLengthElement
		
		public ResourceLengthElement (String uri, int contentLength) {
			this.uri = uri;
			this.contentLength = String.valueOf(contentLength);
			
		}// resourceLengthElement
		
		public ResourceLengthElement (String uri, String contentLength) {
			this.uri = uri;
			this.contentLength = contentLength;
		}// ResourceLengthElement
		
		public String getContentLength() {
			return contentLength;
		}
		
	}// resourceLengthElement

	
	/**
	 * Get a resource path from an URI
	 * @param uri to process
	 * @return the resource path
	 */
	public static String getResourcePath (String uri) {
		int indexLastSlash = uri.lastIndexOf("/");
		if (indexLastSlash == -1) return null;
		else if (indexLastSlash == 0) return "/";
		else return uri.substring(0, indexLastSlash+1);	
	}// getParentUri
	
	
	/**
	 * 
	 * @param uri to process
	 * @param path Does the uri start with this path ?
	 * @return true if the uri starts with the path, else false
	 */
	private boolean match(String uri, String path) {
		boolean result = false;
		
		if (path=="") return true; // no path parameter = all of the tree processed
		
		String [] pathArray = path.split(";");
		
		for (int i=0; i<pathArray.length; i++) {
			result = result || uri.startsWith(pathArray[i]);
		}// for (int i=0; i<pathArray.length; i++)
		
		return result;
	}// match
	
	
	public QuotaListener(){
	    Domain.log("constructeur " + this.hashCode(), LOG_CHANNEL, Logger.DEBUG);
	}// constructor
	
	
	/**
	 * Called before a resource is about to be deleted
	 * - save the resource content lenght for the deleteAfterDelete method
	 */
	public void deleteBeforeDelete(DetailedWebdavEvent event) throws VetoException {
		
		Domain.log("deleteBeforeDelete " + this.hashCode(), LOG_CHANNEL, Logger.DEBUG);
		
		AbstractWebdavMethod method = (AbstractWebdavMethod)event.getSource();
		HttpServletRequest request = method.getRequest();

		String slideContext = request.getContextPath();
    	//String requestUri = request.getRequestURI();
    	//requestUri = requestUri.substring(slideContext.length());
    	String requestUri = event.getDestinationUri();
    	
    	//Is it required ??
    	//requestUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(requestUri));
    	
    	if (!match(requestUri,quotaPath)) {
    		Domain.log("deleteBeforeDelete:requestUri "+requestUri+" does not match with the path "+quotaPath+" >return", LOG_CHANNEL, Logger.DEBUG);
    		return;
    	}// if (!match(requestUri,quotaPath)) {
    	
		Domain.log("deleteBeforeDelete:slideContext="+slideContext, LOG_CHANNEL, Logger.DEBUG);
		Domain.log("deleteBeforeDelete:requestUri="+requestUri, LOG_CHANNEL, Logger.DEBUG);
    	
    	try {
    		QuotaElement quotaElement = new QuotaElement(requestUri, method, QuotaConstants.CONTENT_LENGTH_IN_NRD);
    		String tmpCurrent = quotaElement.getContentLength();
    		tableOfResourceLength.put(requestUri, new ResourceLengthElement(requestUri, tmpCurrent));
    		Domain.log("deleteBeforeDelete:caching "+requestUri+" - contentLength="+tmpCurrent, LOG_CHANNEL, Logger.DEBUG);
    	} catch (IOException e) {
			throw new VetoException("Error parsing the request");
		    // TODO
    	} catch (AccessDeniedException e) {
//			 what should be done here ?
    		Domain.log("deleteBeforeDelete:AccessDeniedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (LinkedObjectNotFoundException e) {
//			 what should be done here ?
			Domain.log("deleteBeforeDelete:LinkedObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionDescriptorNotFoundException e) {
//			 what should be done here ?
			Domain.log("deleteBeforeDelete:RevisionDescriptorNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectLockedException e) {
//			 what should be done here ?
			Domain.log("deleteBeforeDelete:ObjectLockedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectNotFoundException e) {
//			 what should be done here ?
			Domain.log("deleteBeforeDelete:ObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ServiceAccessException e) {
//			 what should be done here ?
			Domain.log("deleteBeforeDelete:ServiceAccessException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (VetoException e) {
//			 what should be done here ?
			Domain.log("deleteBeforeDelete:VetoException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		}
		
	}// deleteBeforeDelete
	
	
	/**
	 * Called after the resource deletion
	 * - get the resource content lenght saved in the deleteBeforeDelete method
	 * - update resource quota MD
	 */
	public void deleteAfterDelete(DetailedWebdavEvent event) throws VetoException {
		
		Domain.log("deleteAfterDelete " + this.hashCode(), LOG_CHANNEL, Logger.DEBUG);
		
		AbstractWebdavMethod method = (AbstractWebdavMethod)event.getSource();
		HttpServletRequest request = method.getRequest();
    	
    	String slideContext = request.getContextPath();
    	//String requestUri = request.getRequestURI();
    	//requestUri = requestUri.substring(slideContext.length());
    	String requestUri = event.getDestinationUri();
    	
    	//Is it required ??
    	//requestUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(requestUri));	
    	
    	if (!match(requestUri,quotaPath)) {
    		Domain.log("put:requestUri "+requestUri+" does not match with the path "+quotaPath+" >return", LOG_CHANNEL, Logger.DEBUG);
    		return;
    	}// if (!match(requestUri,quotaPath)) {
    	
		Domain.log("deleteAfterDelete:slideContext="+slideContext, LOG_CHANNEL, Logger.DEBUG);
		Domain.log("deleteAfterDelete:requestUri="+requestUri, LOG_CHANNEL, Logger.DEBUG);
    	try {   		
    		String tmpCurrent = ((ResourceLengthElement)(tableOfResourceLength.get(requestUri))).getContentLength();
    		QuotaElement quotaElement = new QuotaElement(requestUri, method, tmpCurrent);
    		Domain.log("deleteAfterDelete:updating quota metadata for "+requestUri, LOG_CHANNEL, Logger.DEBUG);
    		quotaElement.updateQuotaMetadata(QuotaConstants.SUBTRACT_QUOTA_USED_BYTES, true);
    		Domain.log("deleteAfterDelete:removing entry "+requestUri+" from hashtable", LOG_CHANNEL, Logger.DEBUG);
    		
    	} catch (ObjectNotFoundException e) {
//    		 what should be done here ?
    		Domain.log("deleteAfterDelete:ObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (AccessDeniedException e) {
//			 what should be done here ?
			Domain.log("deleteAfterDelete:AccessDeniedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (LinkedObjectNotFoundException e) {
//			 what should be done here ?
			Domain.log("deleteAfterDelete:LinkedObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectLockedException e) {
//			 what should be done here ?
			Domain.log("deleteAfterDelete:ObjectLockedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ServiceAccessException e) {
//			 what should be done here ?
			Domain.log("deleteAfterDelete:ServiceAccessException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionDescriptorNotFoundException e) {
//			 what should be done here ?
			Domain.log("deleteAfterDelete:RevisionDescriptorNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionNotFoundException e) {
//			 what should be done here ?
			Domain.log("deleteAfterDelete:RevisionNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (VetoException e) {
//			 what should be done here ?
			Domain.log("deleteAfterDelete:VetoException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} finally {
                        tableOfResourceLength.remove(requestUri);	
		}
		
	}// deleteAfterDelete
	
	
	/**
	 * Called after the resource is put
	 * - get the resource original content lenght (saved in the put method - if the resource already exist)
	 * - get the resource content lenght in the NRD
	 * - update resource quota MD
	 */
	public void putAfter(WebdavEvent event) throws VetoException {
		
		Domain.log("putAfter " + this.hashCode(), LOG_CHANNEL, Logger.DEBUG);
		
		AbstractWebdavMethod method = (AbstractWebdavMethod)event.getSource();
		HttpServletRequest request = method.getRequest();

		String slideContext = request.getContextPath();
    	//String requestUri = request.getRequestURI();
    	//requestUri = requestUri.substring(slideContext.length());
    	//requestUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(requestUri));
    	
		PutMethod putMethod = (PutMethod)method;
    	String requestUri = putMethod.getResourcePath();
    	
    	
    	if (!match(requestUri,quotaPath)) {
    		Domain.log("putAfter:requestUri "+requestUri+" does not match with the path "+quotaPath+" >return", LOG_CHANNEL, Logger.DEBUG);
    		return;
    	}// if (!match(requestUri,quotaPath)) {
    	
		Domain.log("putAfter:slideContext="+slideContext, LOG_CHANNEL, Logger.DEBUG);
		Domain.log("putAfter:requestUri="+requestUri, LOG_CHANNEL, Logger.DEBUG);
    	
    	try {
    		// trying to find the resource in the cache
    		Domain.log("putAfter:trying to find resource "+requestUri+" in the cache", LOG_CHANNEL, Logger.DEBUG);
    		int originalResourceContentLength = 0;
    		if (tableOfResourceLength.containsKey(requestUri)) {
    			String tmp = ((ResourceLengthElement)tableOfResourceLength.get(requestUri)).getContentLength();
    			originalResourceContentLength = Integer.parseInt(tmp);
    			Domain.log("putAfter:resource "+requestUri+" found in the cache - originalResourceContentLength="+originalResourceContentLength, LOG_CHANNEL, Logger.DEBUG);
    		}// if (tableOfResourceLength.containsKey(requestUri))
    			
    		QuotaElement quotaElement = new QuotaElement(requestUri, method, QuotaConstants.CONTENT_LENGTH_IN_NRD);
    		int contentLength = Integer.parseInt(quotaElement.getContentLength());
    		quotaElement = new QuotaElement(requestUri, method, String.valueOf(contentLength-originalResourceContentLength));
    		
    		Domain.log("putAfter:updating quota metadata for "+requestUri, LOG_CHANNEL, Logger.DEBUG);
    		quotaElement.updateQuotaMetadata(QuotaConstants.ADD_QUOTA_USED_BYTES, true);
    		Domain.log("putAfter:removing entry "+requestUri+" from hashtable", LOG_CHANNEL, Logger.DEBUG);
    	} catch (IOException e) {
			throw new VetoException("Error parsing the request");
			// TODO
    	} catch (ObjectNotFoundException e) {
//  		 what should be done here ?
    		Domain.log("putAfter:ObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (AccessDeniedException e) {
//   		 what should be done here ?
			Domain.log("putAfter:AccessDeniedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (LinkedObjectNotFoundException e) {
//   		 what should be done here ?
			Domain.log("putAfter:LinkedObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectLockedException e) {
//   		 what should be done here ?
			Domain.log("putAfter:ObjectLockedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ServiceAccessException e) {
//   		 what should be done here ?
			Domain.log("putAfter:ServiceAccessException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionDescriptorNotFoundException e) {
//   		 what should be done here ?
			Domain.log("putAfter:RevisionDescriptorNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionNotFoundException e) {
//   		 what should be done here ?
			Domain.log("putAfter:RevisionDescriptorNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (VetoException e) {
//   		 what should be done here ?
			Domain.log("putAfter:VetoException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} finally {
			tableOfResourceLength.remove(requestUri);
		}
		
	}// putAfter


	/**
	 * Called after the resource is copied
	 * - get the resource content lenght in the NRD
	 * - update resource quota MD
	 */
	public void copyAfterCopy(DetailedWebdavEvent event) throws VetoException {

		Domain.log("copyAfterCopy", LOG_CHANNEL, Logger.DEBUG);
	
		AbstractWebdavMethod method = (AbstractWebdavMethod)event.getSource();
		SlideToken slideToken = method.getSlideToken();
		HttpServletRequest request = method.getRequest();

		String destinationUri = event.getDestinationUri();
		
		destinationUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(destinationUri));
		
		if (!match(destinationUri,quotaPath)) {
    		Domain.log("copyAfterCopy:destinationUri "+destinationUri+" does not match with the path "+quotaPath+" >return", LOG_CHANNEL, Logger.DEBUG);
    		return;
    	}// if (!match(requestUri,quotaPath)) {
		
		Domain.log("copyAfterCopy:destinationUri="+destinationUri, LOG_CHANNEL, Logger.DEBUG);
    	
    	try {
    		QuotaElement quotaElement = new QuotaElement(destinationUri, method, QuotaConstants.CONTENT_LENGTH_IN_NRD);
    		Domain.log("copyAfterCopy:updating quota metadata for "+destinationUri, LOG_CHANNEL, Logger.DEBUG);
    		quotaElement.updateQuotaMetadata(QuotaConstants.ADD_QUOTA_USED_BYTES, true);
    	} catch (IOException e) {
			throw new VetoException("Error parsing the request");
			// TODO
    	} catch (ObjectNotFoundException e) {
//  		 what should be done here ?
    		Domain.log("copyAfterCopy:ObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (AccessDeniedException e) {
//  		 what should be done here ?
			Domain.log("copyAfterCopy:AccessDeniedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (LinkedObjectNotFoundException e) {
//  		 what should be done here ?
			Domain.log("copyAfterCopy:LinkedObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectLockedException e) {
//  		 what should be done here ?
			Domain.log("copyAfterCopy:ObjectLockedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ServiceAccessException e) {
//  		 what should be done here ?
			Domain.log("copyAfterCopy:ServiceAccessException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionDescriptorNotFoundException e) {
//  		 what should be done here ?
			Domain.log("copyAfterCopy:RevisionDescriptorNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionNotFoundException e) {
//  		 what should be done here ?
			Domain.log("copyAfterCopy:RevisionNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (VetoException e) {
//  		 what should be done here ?
			Domain.log("copyAfterCopy:VetoException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} 
	}
	
	
	/**
	 * Called after the resource deletion
	 * - get the resource content lenght saved in the copyBeforeDelete method
	 * - update resource quota MD
	 */
	public void copyAfterDelete(DetailedWebdavEvent event) throws VetoException {
		
		Domain.log("copyAfterDelete", LOG_CHANNEL, Logger.DEBUG);
		
		AbstractWebdavMethod method = (AbstractWebdavMethod)event.getSource();
		SlideToken slideToken = method.getSlideToken();
		HttpServletRequest request = method.getRequest();

		String destinationUri = event.getDestinationUri();
		
		destinationUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(destinationUri));
		
		if (!match(destinationUri,quotaPath)) {
    		Domain.log("copyAfterDelete:destinationUri "+destinationUri+" does not match with the path "+quotaPath+" >return", LOG_CHANNEL, Logger.DEBUG);
    		return;
    	}// if (!match(requestUri,quotaPath)) {
		
		Domain.log("copyAfterDelete:destinationUri="+destinationUri, LOG_CHANNEL, Logger.DEBUG);

    	try {   		
    		String tmpCurrent = ((ResourceLengthElement)(tableOfResourceLength.get(destinationUri))).getContentLength();
    		QuotaElement quotaElement = new QuotaElement(destinationUri, method, tmpCurrent);
    		Domain.log("copyAfterDelete:updating quota metadata for "+destinationUri, LOG_CHANNEL, Logger.DEBUG);
    		quotaElement.updateQuotaMetadata(QuotaConstants.SUBTRACT_QUOTA_USED_BYTES, true);
    		Domain.log("copyAfterDelete:removing entry "+destinationUri+" from hashtable", LOG_CHANNEL, Logger.DEBUG);
    	} catch (ObjectNotFoundException e) {
// 		 what should be done here ?
    		Domain.log("copyAfterDelete:ObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (AccessDeniedException e) {
// 		 what should be done here ?
			Domain.log("copyAfterDelete:AccessDeniedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (LinkedObjectNotFoundException e) {
// 		 what should be done here ?
			Domain.log("copyAfterDelete:LinkedObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectLockedException e) {
// 		 what should be done here ?
			Domain.log("copyAfterDelete:ObjectLockedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ServiceAccessException e) {
// 		 what should be done here ?
			Domain.log("copyAfterDelete:ServiceAccessException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionDescriptorNotFoundException e) {
// 		 what should be done here ?
			Domain.log("copyAfterDelete:RevisionDescriptorNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionNotFoundException e) {
// 		 what should be done here ?
			Domain.log("copyAfterDelete:RevisionNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (VetoException e) {
// 		 what should be done here ?
			Domain.log("copyAfterDelete:VetoException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} finally {
			tableOfResourceLength.remove(destinationUri);
		}
	}
	
	
	/**
	 * Called before a resource is about to be copied
	 * - throw a 507 error if the quota will be exceeded while copying the resource
	 */
	public void copyBeforeCopy(DetailedWebdavEvent event) throws VetoException {
		
		Domain.log("copyBeforeCopy", LOG_CHANNEL, Logger.DEBUG);
		
		AbstractWebdavMethod method = (AbstractWebdavMethod)event.getSource();
		SlideToken slideToken = method.getSlideToken();
		HttpServletRequest request = method.getRequest();

		String sourceUri = event.getSourceUri();
		String destinationUri = event.getDestinationUri();
		
		sourceUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(sourceUri));
		destinationUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(destinationUri));
		
		if (!match(destinationUri,quotaPath)) {
    		Domain.log("put:destinationUri "+destinationUri+" does not match with the path "+quotaPath+" >return", LOG_CHANNEL, Logger.DEBUG);
    		return;
    	}// if (!match(requestUri,quotaPath)) {
		
		Domain.log("copyBeforeCopy:sourceUri="+sourceUri, LOG_CHANNEL, Logger.DEBUG);
		Domain.log("copyBeforeCopy:destinationUri="+destinationUri, LOG_CHANNEL, Logger.DEBUG);
		
    	try {

    		QuotaElement quotaElementSource = new QuotaElement(sourceUri, method, QuotaConstants.CONTENT_LENGTH_IN_NRD);
    		String sourceContentLength = quotaElementSource.getContentLength();
    		QuotaElement quotaElementDestination = new QuotaElement(destinationUri, method, sourceContentLength);
    		
    		quotaElementDestination.initStorageAction();  		

    		if (quotaElementDestination.hasQuota()) {
    			if (quotaElementDestination.quotaExceeded()) {
    				Domain.log("copyBeforeCopy:quota exceeded for "+destinationUri, LOG_CHANNEL, Logger.INFO);
    				// getting the connected user
    				String connectedUser = slideToken.getCredentialsToken().getPrincipal().getName();
    				
    				// throw a VetoException
    				InsufficientStorageException insufficientStorageException = new InsufficientStorageException(destinationUri, connectedUser, QuotaConstants.QUOTA_EXCEEDED);
    				VetoException vetoException = new VetoException(QuotaConstants.QUOTA_EXCEEDED);
    				vetoException.initCause(insufficientStorageException);
    				throw vetoException;
    			}// (quotaElement.quotaExceeded())
    			else Domain.log("copyBeforeCopy:quota not exceeded for "+destinationUri, LOG_CHANNEL, Logger.DEBUG);
    		}// if (quotaElement.hasQuota())
    		else Domain.log("copyBeforeCopy:no quota for "+destinationUri, LOG_CHANNEL, Logger.DEBUG);
    	
    	} catch (IOException e) {
			throw new VetoException("Error parsing the request");
			// TODO
    	} catch (ObjectNotFoundException e) {
//    		 what should be done here ?
    		Domain.log("copyBeforeCopy:ObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (AccessDeniedException e) {
//	 		 what should be done here ?
			Domain.log("copyBeforeCopy:AccessDeniedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (LinkedObjectNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("copyBeforeCopy:LinkedObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectLockedException e) {
//	 		 what should be done here ?
			Domain.log("copyBeforeCopy:ObjectLockedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ServiceAccessException e) {
//	 		 what should be done here ?
			Domain.log("copyBeforeCopy:ObjectLockedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionDescriptorNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("copyBeforeCopy:RevisionDescriptorNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		}
		
		// in case of security problems...
//		SlideToken systemToken = new SlideTokenWrapper(slideToken);
//		systemToken.setForceSecurity(false);
//		systemToken.setForceLock(false); 
		
	}
	
	
	/**
	 * Called before a resource is about to be deleted
	 * - save the resource content lenght for the copyAfterDelete method
	 */
	public void copyBeforeDelete(DetailedWebdavEvent event) throws VetoException {
		Domain.log("copyBeforeDelete", LOG_CHANNEL, Logger.DEBUG);
		
		AbstractWebdavMethod method = (AbstractWebdavMethod)event.getSource();
		SlideToken slideToken = method.getSlideToken();
		HttpServletRequest request = method.getRequest();

		String destinationUri = event.getDestinationUri();
		
		destinationUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(destinationUri));
		
		if (!match(destinationUri,quotaPath)) {
    		Domain.log("copyBeforeDelete:destinationUri "+destinationUri+" does not match with the path "+quotaPath+" >return", LOG_CHANNEL, Logger.DEBUG);
    		return;
    	}// if (!match(requestUri,quotaPath)) {
		
		Domain.log("copyBeforeDelete:destinationUri="+destinationUri, LOG_CHANNEL, Logger.DEBUG);
		
    	try {
    		QuotaElement quotaElement = new QuotaElement(destinationUri, method, QuotaConstants.CONTENT_LENGTH_IN_NRD);
    		String tmpCurrent = quotaElement.getContentLength();
    		tableOfResourceLength.put(destinationUri, new ResourceLengthElement(destinationUri, tmpCurrent));
    		Domain.log("copyBeforeDelete:caching "+destinationUri+" - contentLength="+tmpCurrent, LOG_CHANNEL, Logger.DEBUG);
    	} catch (IOException e) {
			throw new VetoException("Error parsing the request");
			// TODO
    	} catch (AccessDeniedException e) {
//	 		 what should be done here ?
    		Domain.log("copyBeforeDelete:AccessDeniedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (LinkedObjectNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("copyBeforeDelete:LinkedObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionDescriptorNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("copyBeforeDelete:RevisionDescriptorNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectLockedException e) {
//	 		 what should be done here ?
			Domain.log("copyBeforeDelete:ObjectLockedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("copyBeforeDelete:ObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ServiceAccessException e) {
//	 		 what should be done here ?
			Domain.log("copyBeforeDelete:ServiceAccessException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (VetoException e) {
//	 		 what should be done here ?
			Domain.log("copyBeforeDelete:VetoException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		}
	}
	
	
	/**
	 * Called after the resource is copied
	 * - get the resource content lenght in the NRD
	 * - update resource quota MD
	 */
	public void moveAfterCopy(DetailedWebdavEvent event) throws VetoException {
		
		Domain.log("moveAfterCopy", LOG_CHANNEL, Logger.DEBUG);
		
		AbstractWebdavMethod method = (AbstractWebdavMethod)event.getSource();
		SlideToken slideToken = method.getSlideToken();
		HttpServletRequest request = method.getRequest();

		String destinationUri = event.getDestinationUri();
		
		destinationUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(destinationUri));
		
		if (!match(destinationUri,quotaPath)) {
    		Domain.log("moveAfterCopy:destinationUri "+destinationUri+" does not match with the path "+quotaPath+" >return", LOG_CHANNEL, Logger.DEBUG);
    		return;
    	}// if (!match(requestUri,quotaPath)) {
		
		Domain.log("moveAfterCopy:destinationUri="+destinationUri, LOG_CHANNEL, Logger.DEBUG);
    	
    	try {
    		QuotaElement quotaElement = new QuotaElement(destinationUri, method, QuotaConstants.CONTENT_LENGTH_IN_NRD);
    		Domain.log("moveAfterCopy:updating quota metadata for "+destinationUri, LOG_CHANNEL, Logger.DEBUG);
    		quotaElement.updateQuotaMetadata(QuotaConstants.ADD_QUOTA_USED_BYTES, true);
    	} catch (IOException e) {
			throw new VetoException("Error parsing the request");
			// TODO
    	} catch (ObjectNotFoundException e) {
//	 		 what should be done here ?
    		Domain.log("moveAfterCopy:ObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (AccessDeniedException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterCopy:AccessDeniedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (LinkedObjectNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterCopy:LinkedObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectLockedException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterCopy:ObjectLockedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ServiceAccessException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterCopy:ServiceAccessException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionDescriptorNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterCopy:RevisionDescriptorNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterCopy:RevisionNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (VetoException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterCopy:VetoException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		}
	}
	
	
	/**
	 * Called after the resource deletion
	 * - get the resource content lenght saved in the moveBeforeDelete method
	 * - update resource quota MD
	 */
	public void moveAfterDelete(DetailedWebdavEvent event) throws VetoException {
		
		Domain.log("moveAfterDelete", LOG_CHANNEL, Logger.DEBUG);
		
		Domain.log("moveAfterDelete", LOG_CHANNEL, Logger.DEBUG);
		
		AbstractWebdavMethod method = (AbstractWebdavMethod)event.getSource();
		SlideToken slideToken = method.getSlideToken();
		HttpServletRequest request = method.getRequest();

		String destinationUri = event.getDestinationUri();
		
		destinationUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(destinationUri));
		
		if (!match(destinationUri,quotaPath)) {
    		Domain.log("put:destinationUri "+destinationUri+" does not match with the path "+quotaPath+" >return", LOG_CHANNEL, Logger.DEBUG);
    		return;
    	}// if (!match(requestUri,quotaPath)) {
		
		Domain.log("moveAfterDelete:destinationUri="+destinationUri, LOG_CHANNEL, Logger.DEBUG);

    	try {   		
    		String tmpCurrent = ((ResourceLengthElement)(tableOfResourceLength.get(destinationUri))).getContentLength();
    		QuotaElement quotaElement = new QuotaElement(destinationUri, method, tmpCurrent);
    		Domain.log("moveAfterDelete:updating quota metadata for "+destinationUri, LOG_CHANNEL, Logger.DEBUG);
    		quotaElement.updateQuotaMetadata(QuotaConstants.SUBTRACT_QUOTA_USED_BYTES, true);
    		Domain.log("moveAfterDelete:removing entry "+destinationUri+" from hashtable", LOG_CHANNEL, Logger.DEBUG);
    	} catch (ObjectNotFoundException e) {
//	 		 what should be done here ?
    		Domain.log("moveAfterDelete:ObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (AccessDeniedException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterDelete:AccessDeniedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (LinkedObjectNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterDelete:LinkedObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectLockedException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterDelete:ObjectLockedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ServiceAccessException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterDelete:ServiceAccessException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionDescriptorNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterDelete:RevisionDescriptorNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterDelete:RevisionNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (VetoException e) {
//	 		 what should be done here ?
			Domain.log("moveAfterDelete:VetoException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} finally {
			tableOfResourceLength.remove(destinationUri);
		}
		
	}
	
	
	/**
	 * Called before a resource is about to be moved
	 * - throw a 507 error if the quota will be exceeded while copying the resource
	 */
	public void moveBeforeCopy(DetailedWebdavEvent event) throws VetoException {
		
		Domain.log("moveBeforeCopy", LOG_CHANNEL, Logger.DEBUG);
		
		boolean resourceIsRenamed = false;
		
		AbstractWebdavMethod method = (AbstractWebdavMethod)event.getSource();
		SlideToken slideToken = method.getSlideToken();
		HttpServletRequest request = method.getRequest();

		String sourceUri = event.getSourceUri();
		String destinationUri = event.getDestinationUri();
		
		sourceUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(sourceUri));
		destinationUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(destinationUri));
		
		if (!match(destinationUri,quotaPath)) {
    		Domain.log("moveBeforeCopy:destinationUri "+destinationUri+" does not match with the path "+quotaPath+" >return", LOG_CHANNEL, Logger.DEBUG);
    		return;
    	}// if (!match(requestUri,quotaPath)) {
		
		Domain.log("moveBeforeCopy:sourceUri="+sourceUri, LOG_CHANNEL, Logger.DEBUG);
		Domain.log("moveBeforeCopy:destinationUri="+destinationUri, LOG_CHANNEL, Logger.DEBUG);
		
		// when a resource is about to be renamed, the moveBeforeCopy method is called
		// improvement TODO : not substract/add quota-used-bytes
		if (getResourcePath(sourceUri).equals(getResourcePath(destinationUri))) {
			Domain.log("moveBeforeCopy:resource "+sourceUri+" is about to be renamed, not quota check", LOG_CHANNEL, Logger.DEBUG);
			resourceIsRenamed = true;
		}// if (getResourcePath(sourceUri).equals(getResourcePath(destinationUri))
		
			try {
				
				QuotaElement quotaElementSource = new QuotaElement(sourceUri, method, QuotaConstants.CONTENT_LENGTH_IN_NRD);
				String sourceContentLength = quotaElementSource.getContentLength();
				QuotaElement quotaElementDestination = new QuotaElement(destinationUri, method, sourceContentLength);
				
				quotaElementDestination.initStorageAction();  		
				
				if (!resourceIsRenamed && quotaElementDestination.hasQuota()) {
					if (quotaElementDestination.quotaExceeded()) {
						Domain.log("moveBeforeCopy:quota exceeded for "+destinationUri, LOG_CHANNEL, Logger.INFO);
						// getting the connected user
						String connectedUser = slideToken.getCredentialsToken().getPrincipal().getName();
						
						// throw a VetoException
						InsufficientStorageException insufficientStorageException = new InsufficientStorageException(destinationUri, connectedUser, QuotaConstants.QUOTA_EXCEEDED);
						VetoException vetoException = new VetoException(QuotaConstants.QUOTA_EXCEEDED);
						vetoException.initCause(insufficientStorageException);
						throw vetoException;
					}// (quotaElement.quotaExceeded())
					else Domain.log("moveBeforeCopy:quota not exceeded for "+destinationUri, LOG_CHANNEL, Logger.DEBUG);
				}// if (quotaElement.hasQuota())
				else Domain.log("moveBeforeCopy:no quota for "+destinationUri, LOG_CHANNEL, Logger.DEBUG);
				
			} catch (IOException e) {
				throw new VetoException("Error parsing the request");
				// TODO
			} catch (ObjectNotFoundException e) {
//				what should be done here ?
				Domain.log("moveBeforeCopy:ObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
			} catch (AccessDeniedException e) {
//				what should be done here ?
				Domain.log("moveBeforeCopy:AccessDeniedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
			} catch (LinkedObjectNotFoundException e) {
//				what should be done here ?
				Domain.log("moveBeforeCopy:LinkedObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
			} catch (ObjectLockedException e) {
//				what should be done here ?
				Domain.log("moveBeforeCopy:ObjectLockedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
			} catch (ServiceAccessException e) {
//				what should be done here ?
				Domain.log("moveBeforeCopy:ServiceAccessException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
			} catch (RevisionDescriptorNotFoundException e) {
//				what should be done here ?
				Domain.log("moveBeforeCopy:RevisionDescriptorNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
			}
				
		// in case of security problems...
//		SlideToken systemToken = new SlideTokenWrapper(slideToken);
//		systemToken.setForceSecurity(false);
//		systemToken.setForceLock(false); 
		
	}
	
	
	/**
	 * Called before a resource is about to be moved
	 * - save the resource content lenght for the moveAfterDelete method
	 */
	public void moveBeforeDelete(DetailedWebdavEvent event) throws VetoException {
		Domain.log("moveBeforeDelete", LOG_CHANNEL, Logger.DEBUG);
		
		AbstractWebdavMethod method = (AbstractWebdavMethod)event.getSource();
		SlideToken slideToken = method.getSlideToken();
		HttpServletRequest request = method.getRequest();

		String destinationUri = event.getDestinationUri();
		
		destinationUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(destinationUri));
		
		if (!match(destinationUri,quotaPath)) {
    		Domain.log("put:destinationUri "+destinationUri+" does not match with the path "+quotaPath+" >return", LOG_CHANNEL, Logger.DEBUG);
    		return;
    	}// if (!match(requestUri,quotaPath)) {
		
		Domain.log("moveBeforeDelete:destinationUri="+destinationUri, LOG_CHANNEL, Logger.DEBUG);
		
    	try {
    		QuotaElement quotaElement = new QuotaElement(destinationUri, method, QuotaConstants.CONTENT_LENGTH_IN_NRD);
    		String tmpCurrent = quotaElement.getContentLength();
    		tableOfResourceLength.put(destinationUri, new ResourceLengthElement(destinationUri, tmpCurrent));
    		Domain.log("moveBeforeDelete:caching "+destinationUri+" - contentLength="+tmpCurrent, LOG_CHANNEL, Logger.DEBUG);
		
    	} catch (IOException e) {
			throw new VetoException("Error parsing the request");
			// TODO
    	} catch (AccessDeniedException e) {
//	 		 what should be done here ?
    		Domain.log("moveBeforeDelete:AccessDeniedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (LinkedObjectNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("moveBeforeDelete:LinkedObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionDescriptorNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("moveBeforeDelete:RevisionDescriptorNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectLockedException e) {
//	 		 what should be done here ?
			Domain.log("moveBeforeDelete:ObjectLockedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("moveBeforeDelete:ObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ServiceAccessException e) {
//	 		 what should be done here ?
			Domain.log("moveBeforeDelete:ServiceAccessException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (VetoException e) {
//	 		 what should be done here ?
			Domain.log("moveBeforeCopy:VetoException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		}
	}
	
	
	/**
	 * Called before a resource is about to be put
	 * - check if the resource already exist and then save its content lenght
	 * - throw a 507 error if the quota will be exceeded while puting the resource
	 */
	public void put(WebdavEvent event) throws VetoException {
		
		Domain.log("put " + this.hashCode(), LOG_CHANNEL, Logger.DEBUG);

		AbstractWebdavMethod method = (AbstractWebdavMethod)event.getSource();
		SlideToken slideToken = method.getSlideToken();
		HttpServletRequest request = method.getRequest();

		String slideContext = request.getContextPath();
    	//String requestUri = request.getRequestURI();
    	//requestUri = requestUri.substring(slideContext.length());
    	//requestUri = WebdavUtils.normalizeURL(WebdavUtils.fixTomcatURL(requestUri));
    	
    	PutMethod putMethod = (PutMethod)method;
    	String requestUri = putMethod.getResourcePath();
    	
    	
    	if (!match(requestUri,quotaPath)) {
    		Domain.log("put:requestUri "+requestUri+" does not match with the path "+quotaPath+" >return", LOG_CHANNEL, Logger.DEBUG);
    		return;
    	}// if (!match(requestUri,quotaPath)) {
    	
		Domain.log("put:slideContext="+slideContext, LOG_CHANNEL, Logger.DEBUG);
		Domain.log("put:requestUri="+requestUri, LOG_CHANNEL, Logger.DEBUG);
	
		try {

    		// check if the resource already exists (required only for a put method)
			// it would be better to find a better method...
    		boolean resourceExists = false;
    		String originalResourceContentLength = null;
    		
    		Domain.log("put:checking if the resource already exists", LOG_CHANNEL, Logger.DEBUG);
    		try {
    			Content content = method.getContent();
				NodeRevisionDescriptors nrds = content.retrieve(slideToken, requestUri);
				NodeRevisionDescriptor nrd = content.retrieve(slideToken, nrds);
				originalResourceContentLength = (nrd.getProperty(QuotaConstants.NRD_CONTENT_LENGTH, QuotaConstants.NAMESPACE_DAV).getValue()).toString();
				
				if (originalResourceContentLength.equals("0")) {
					Domain.log("put:resource "+requestUri+" does NOT exists or size=0", LOG_CHANNEL, Logger.DEBUG);
					resourceExists = false;
				}// if (originalResourceContentLength.equals("0"))
				else {
					Domain.log("put:resource "+requestUri+" already exists - originalResourceContentLength="+originalResourceContentLength, LOG_CHANNEL, Logger.DEBUG);
					resourceExists = true;
				}// else (originalResourceContentLength.equals("0"))
				
			} catch (ObjectNotFoundException e) {
				Domain.log("put:resource "+requestUri+" does NOT exists", LOG_CHANNEL, Logger.DEBUG);
			}
    		
    		QuotaElement quotaElement;
			quotaElement = new QuotaElement(requestUri, method, QuotaConstants.CONTENT_LENGTH_IN_REQUEST);
			quotaElement.initStorageAction();  		

    		if (quotaElement.hasQuota()) {
    			if (quotaElement.quotaExceeded()) {
    				Domain.log("put:quota exceeded for "+requestUri, LOG_CHANNEL, Logger.INFO);
    				// getting the connected user
    				String connectedUser = slideToken.getCredentialsToken().getPrincipal().getName();
    				
    				// throw a VetoException
    				InsufficientStorageException insufficientStorageException = new InsufficientStorageException(requestUri, connectedUser, QuotaConstants.QUOTA_EXCEEDED);
    				VetoException vetoException = new VetoException(QuotaConstants.QUOTA_EXCEEDED);
    				vetoException.initCause(insufficientStorageException);
    				throw vetoException;
    			}// (quotaElement.quotaExceeded())
    			else {
    				Domain.log("put:quota not exceeded for "+requestUri, LOG_CHANNEL, Logger.DEBUG);
    				
    				// if the resource already exist then caching its content length
    	    		if (resourceExists) {
    	    			tableOfResourceLength.put(requestUri, new ResourceLengthElement(requestUri, originalResourceContentLength));
    	        		Domain.log("put:caching "+requestUri+" - originalResourceContentLength="+originalResourceContentLength, LOG_CHANNEL, Logger.DEBUG);
    	    		}// if (resourceExists)
    	    		
    			}// else (quotaElement.quotaExceeded())
    		}// if (quotaElement.hasQuota())
    		else Domain.log("put:no quota for "+requestUri, LOG_CHANNEL, Logger.DEBUG);
    		
		} catch (IOException e) {
			throw new VetoException("Error parsing the request");
			// TODO
    	} catch (ObjectNotFoundException e) {
//	 		 what should be done here ?
    		Domain.log("put:ObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (AccessDeniedException e) {
//	 		 what should be done here ?
			Domain.log("put:AccessDeniedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (LinkedObjectNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("put:LinkedObjectNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ObjectLockedException e) {
//	 		 what should be done here ?
			Domain.log("put:ObjectLockedException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (ServiceAccessException e) {
//	 		 what should be done here ?
			Domain.log("put:ServiceAccessException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} catch (RevisionDescriptorNotFoundException e) {
//	 		 what should be done here ?
			Domain.log("put:RevisionDescriptorNotFoundException!:"+e.toString(), LOG_CHANNEL, Logger.ERROR);
		} 
		
		// in case of security problems...
//		SlideToken systemToken = new SlideTokenWrapper(slideToken);
//		systemToken.setForceSecurity(false);
//		systemToken.setForceLock(false); 
		
	}// put


	public void retrieve(ContentEvent event) throws VetoException {
	}

	public void store(ContentEvent event) throws VetoException {
	}

	public void create(ContentEvent event) throws VetoException {
	}

	public void remove(ContentEvent event) throws VetoException {
	}

	public void fork(ContentEvent event) throws VetoException {
	}

	public void merge(ContentEvent event) throws VetoException {
	}

	public void configure(Configuration configuration) throws ConfigurationException {
		quotaPath = configuration.getConfiguration("path").getValue();
		Domain.log("configure:path="+quotaPath, LOG_CHANNEL, Logger.DEBUG);
	}
	
}// QuotaListener
