/*
 * LICENCE[[
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1/CeCILL 2.O 
 *
 * The contents of this file are subject to the Mozilla Public License Version 
 * 1.1 (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.mozilla.org/MPL/ 
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, 
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
 * for the specific language governing rights and limitations under the 
 * License. 
 * 
 * The Original Code is utc.fr code. 
 * 
 * The Initial Developer of the Original Code is 
 * Universite de Technologie de Compiegne. 
 * 
 * Portions created by the Initial Developer are Copyright (C) 2005 
 * the Initial Developer. All Rights Reserved. 
 * 
 * Contributor(s): 
 * 
 * 
 * Alternatively, the contents of this file may be used under the terms of 
 * either of the GNU General Public License Version 2 or later (the "GPL"), 
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 
 * or the CeCILL Licence Version 2.0 (http://www.cecill.info/licences.en.html), 
 * in which case the provisions of the GPL, the LGPL or the CeCILL are applicable 
 * instead of those above. If you wish to allow use of your version of this file 
 * only under the terms of either the GPL or the LGPL, and not to allow others 
 * to use your version of this file under the terms of the MPL, indicate your 
 * decision by deleting the provisions above and replace them with the notice 
 * and other provisions required by the GPL or the LGPL. If you do not delete 
 * the provisions above, a recipient may use your version of this file under 
 * the terms of any one of the MPL, the GPL, the LGPL or the CeCILL.
 * ]]LICENCE
 */
const HTTPDATASERVER_CONTRACTID = '@scenari.com/httpdataserver;1';
const HTTPDATASERVER_CID = Components.ID('{98C2A73F-E9A7-4EAA-94C7-4771E5C359EF}');
const HTTPDATASERVER_IID = Components.interfaces.scIDataServer;

/* The Http data server. */
function scHttpDataServer() {
}

/* The OS 
	affecte dans gOS une string contenant le nom de l'OS :
	Win, Mac, UNIX
*/
var gOS="";
function getOS() {
	try{
		if(gOS) return gOS;
		
		var platform = Components.classes["@mozilla.org/network/protocol;1?name=http"].getService(Components.interfaces.nsIHttpProtocolHandler);
		platform = platform.oscpu.toLowerCase();
		if(platform.indexOf("win") != -1)
			gOS = "Win";
		else if(platform.indexOf("mac") != -1)
			gOS = "Mac";
		else if(platform.indexOf("unix") != -1 || platform.indexOf("linux") != -1 || platform.indexOf("sun") != -1)
			gOS = "UNIX";
		else
			gOS = "";
		//debug("OS = "+gOS+" ("+platform+")");
	}catch(e){
		debug("OS unknown: "+e);
	}	
			
}

/* Définition du Http data server. */
scHttpDataServer.prototype = {

	/**
	 *
	 */
	init : function(pUrlServer, pCdUniverse, pAccount, pPassword) {
		var vPrefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
		if(this.fUrlServerLocal) {
			//serveur local privé initialisé -> on le quitte.
			this.quit();
		}
		var vConsoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
		//vConsoleService.logStringMessage("Initialisation du server : "+pUrlServer+"/"+pCdUniverse+"@"+pAccount);
		//vConsoleService.logStringMessage("init..."+pUrlServer);
		
		this.fTitle="";
		this.fUrlServer = pUrlServer;
		this.fUrlIni = pUrlServer;
		this.fPathService = "/s";
		this.fPathAgent = "/a";
		try {
			this.fCdUnivers = pCdUniverse || vPrefs.getCharPref("scenari.defaultUniversCode");
		} catch(e){
			vConsoleService.logStringMessage("pref 'scenari.defaultUniversCode' undefined. "+e);
			this.fCdUnivers = "cms";
		}
		//vConsoleService.logStringMessage("init...CdUniverse::::"+this.fCdUnivers);
		this.fUser = {fAccount:pAccount, fPassword:pPassword};
		// this.fUser = {fAccount:"sys", fPassword:"test"};
		this.fUrlServerLocal = null;
		this.fIsOwnerServerLocal = false;

		//vConsoleService.logStringMessage("server::"+this.fUrlServer);
		var vPrefixLocal = "serverlocal:";
		if(this.fUrlServer.substring(0, vPrefixLocal.length) == vPrefixLocal) {
			//On memorise l'url initiale.
			this.fUrlServerLocal = this.fUrlServer;
			var vEndIdx = this.fUrlServer.indexOf("/", vPrefixLocal.length-1);
			if(vEndIdx<0) {
				vPort = this.fUrlServer.substring(vPrefixLocal.length);
				this.fUrlServer = "http://127.0.0.1:"+vPort;
			} else if(vEndIdx==vPrefixLocal.length){
				vPort = "8017"; //Port par d?faut
				this.fUrlServer = "http://127.0.0.1:"+vPort;
			} else {
				vPort = this.fUrlServer.substring(10, vEndIdx);
				this.fUrlServer = "http://127.0.0.1:"+vPort+this.fUrlServerLocal.substring(vEndIdx);
			}
			try{
				vConsoleService.logStringMessage("Lancement du serveur local : "+this.fUrlServer+" - "+this.fCdUnivers+ " @"+this.fUser.fAccount);
				
				var vFolderService = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
				fLocalServer = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
				var vFile = vFolderService.get("ARes", Components.interfaces.nsIFile).parent.parent;//répertoire bin
				var vAppDirPath = vFile.path;
				//debug("vAppDirPath:: "+vAppDirPath);
				var vOpts = [];
				var vIdxOpt = 0;
				
				getOS();
				
				if(gOS=="Win" || gOS=="UNIX" || gOS=="Mac"){ 
					var vSeparator = gOS=="Win" ? "\\" : "/";
					var vClassPathSeparator = gOS=="Win" ? ";" : ":";
//					debug("vSeparator:: "+vSeparator);
//					debug("vClassPathSeparator:: "+vClassPathSeparator);
					
					var vScLibPath 		= vAppDirPath + vSeparator + "scServer" + vSeparator + "sclib";
					var vJavaLibPath 	= vAppDirPath + vSeparator + "scServer" + vSeparator + "javalib";
					var httpPublicPath	= vAppDirPath + vSeparator + "scServer" + vSeparator + "httppublic";

					var vJavaEndorsedPath 	= vAppDirPath + vSeparator + "scServer" + vSeparator + "jre" + vSeparator + "lib" + vSeparator + "endorsed";
					var vScConfPath 		= vAppDirPath + vSeparator + "scServer" + vSeparator + "conf";
//					debug("vScLibPath:: "+vScLibPath);
//					debug("vJavaLibPath:: "+vJavaLibPath);
//					debug("httpPublicPath:: "+httpPublicPath);
//					debug("vJavaEndorsedPath:: "+vJavaEndorsedPath);
//					debug("vScConfPath:: "+vScConfPath);

					if (gOS == "Mac"){
						vFile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
						vFile.initWithPath("/usr/bin/java");
					} else {
						vFile.append("scServer");
						vFile.append("jre");
						vFile.append("bin");
						gOS=="Win" ? vFile.append("javaw.exe") : vFile.append("java");
					}
//					debug("vFile:: "+vFile);

					vOpts[vIdxOpt++] = "-Duser.dir=" + vAppDirPath;
					vOpts[vIdxOpt++] = "-classpath";
					//vOpts[vIdxOpt++] = "";
					vOpts[vIdxOpt] = vScLibPath + vSeparator + "scenari_bdp.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vScLibPath + vSeparator + "scenari_bdp_fs.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vScLibPath + vSeparator + "scenari_client.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vScLibPath + vSeparator + "scenari_co.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vScLibPath + vSeparator + "scenari_ext.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vScLibPath + vSeparator + "scenari_fw.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vScLibPath + vSeparator + "scenari_ge.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vScLibPath + vSeparator + "scenari_servletengine.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vScLibPath + vSeparator + "scenari_ihmcms.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vScLibPath + vSeparator + "scenari_xsldom.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vScLibPath + vSeparator + "scenari_jing.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vScLibPath + vSeparator + "scenari_updt.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vScLibPath + vSeparator + "scenari_audio.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "avalon.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "batik.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "beanshell.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "beanutils.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "commons-collections.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "commons-logging.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "commons-grant.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "cos.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "dom4j.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "fileupload.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "fop.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "iText.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "jelly.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "jelly.util.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "jelly.xml.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "jelly.ant.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "ant.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "ant.launcher.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "ant.nodeps.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "jexsl.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "servlet.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "webmacro.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "piccolo.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "xerces.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "xmlapi.jar" + vClassPathSeparator;
					vOpts[vIdxOpt] += vJavaLibPath + vSeparator + "unofinder.jar" + vClassPathSeparator; 
					vOpts[vIdxOpt] += httpPublicPath + vSeparator + "applets" + vSeparator + "classes" + vClassPathSeparator;
					vIdxOpt++;
					//vOpts[vIdxOpt++] = "-verbose:gc";
					if(vPrefs.getIntPref("network.proxy.type") > 0){
						vOpts[vIdxOpt++] = "-DproxySet=true";
						vOpts[vIdxOpt++] = "-Dhttp.proxyHost="+vPrefs.getCharPref("network.proxy.ftp");
						vOpts[vIdxOpt++] = "-Dhttp.proxyPort="+vPrefs.getIntPref("network.proxy.ftp_port");
						vOpts[vIdxOpt++] = "-Dhttp.nonProxyHosts"+vPrefs.getCharPref("network.proxy.no_proxies_on").replace(",","|").replace(" ","");
					}
					if (gOS == "Mac"){
						vOpts[vIdxOpt++] = "-Xdock:name=SCENARIserver";
						vOpts[vIdxOpt++] = "-Dcom.apple.macos.useScreenMenuBar=false";
						vOpts[vIdxOpt++] = "-Dcom.apple.macosx.useScreenMenuBar=false";
						vOpts[vIdxOpt++] = "-Djava.endorsed.dirs="+vJavaEndorsedPath;
					} else {
						vOpts[vIdxOpt++] = "-Xms"+vPrefs.getCharPref("scenari.jvm.xms");
						vOpts[vIdxOpt++] = "-Xmx"+vPrefs.getCharPref("scenari.jvm.xmx");
					}
					vOpts[vIdxOpt++] = "com.scenari.c.chain2.EChain2Main";
					if (gOS == "Mac"){
						vOpts[vIdxOpt++] = "file:" + vScConfPath + vSeparator + "init.xml";
					} else {
						vOpts[vIdxOpt++] = "file:scServer" + vSeparator + "conf" + vSeparator + "init.xml";
					}
					vOpts[vIdxOpt++] = vPort;
				} //Fin cas os==Win,Mac,UNIX
				else {
					// TODO : traitement si os ni Mac ni Win	
				}
				if(!vFile.exists()){
					var vWinWatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].getService(Components.interfaces.nsIWindowWatcher);
					var vActiveWindow = vWinWatch.activeWindow.alert("Des éléments de l'application sont manquants.\nVeuillez redémarrer votre ordinateur et réinstaller l'application.");
					throw {toString:function(){return "Fichier introuvable : '" + vFile.path + "'. Réinstaller l'application aprés un redémarrage de l'ordinateur."}};
				}
				fLocalServer.init(vFile);
				fLocalServer.run(false, vOpts, vIdxOpt);
				this.fIsOwnerServerLocal = true;
				//Creation du timer qui maintient la JVM en vie.
				this.fTimerKeepAlive = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
				this.fTimerKeepAlive.initWithCallback(new KeepAliveServer(this), 25000, 1);
			} catch (e){
				vConsoleService.logStringMessage("Connection on server failed. Port : "+vPort+".\n("+e+")");
			}
		}
		
		this.fUrlService = this.fUrlServer+this.fPathService+"/"+this.fCdUnivers;
		this.fUrlAgent = this.fUrlServer+this.fPathAgent+"/"+this.fCdUnivers+"/";
		
		this.fItemListeners = {};
		this.fItemsListeners = null;
	},
	
	isServerReady : function (){
		try{
			var vReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
			var vUrl = this.fUrlServer+this.fPathService+"/"+this.fCdUnivers+"/u/ping";
			vReq.open("GET", vUrl, false, this.fUser.fAccount, this.fUser.fPassword);
			vReq.send(null);
			if(vReq.status == 200) return true;
		} catch(e){}
		return false;
	},
	isServerLocal : function (){
		return (this.fUrlServerLocal || this.fUrlServer.indexOf("127.0.0.1")>=0);
	},
	
	quit : function (){
		if(this.fUrlServerLocal && this.fIsOwnerServerLocal) {
			try{
				var vReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
				var vUrl = this.fUrlServer+this.fPathService+"/"+this.fCdUnivers+"/u/quitter";
				vReq.open("GET", vUrl, false, this.fUser.fAccount, this.fUser.fPassword);
				vReq.send(null);
			} catch(e){}
		}
		this.fUrlServer = null;
		this.fCdUnivers = null;
		this.fUser = null;
		this.fUrlServerLocal = null;
		this.fIsOwnerServerLocal = false;
		this.fUrlService = null;
		this.fUrlAgent = null;
		this.fItemListeners = null;
		this.fItemsListeners = null;
	},
	
	getAgentUrl : function(pIdInstance, pUrlDialogAndParams){
		return this.fUrlAgent + pIdInstance + pUrlDialogAndParams;
	},

	getServiceUrl : function(pUrlDialogAndParams){
		return this.fUrlService + pUrlDialogAndParams;
	},
	
	getSourceUrl : function(pCdSource){
		if(pCdSource == "publichtml") {
			return this.fUrlServer;
		} else {
			return this.fUrlService + "/u/" + pCdSource;
		}
	},
	
	getIniUrl : function(){
		return this.fUrlIni;
	}, 
	
	getDomFromService : function (pUrlDialogAndParams) {
		var vUrl = this.fUrlService+pUrlDialogAndParams;
		var vReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
		//vReq.open("GET", vUrl, false, this.fUser.fAccount, this.fUser.fPassword);
		vReq.open("GET", vUrl, false, this.fUser.fAccount, this.fUser.fPassword);
		vReq.send(null);
		var vResp = vReq.responseXML;
		return vResp;
	},

	getTextFromService : function (pUrlDialogAndParams) {
		var vUrl = this.fUrlService+pUrlDialogAndParams;
		var vReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
		vReq.open("GET", vUrl, false, this.fUser.fAccount, this.fUser.fPassword);
		vReq.send(null);
		var vResp = vReq.responseText;
		return vResp;
	},

	dialogSynchWithService : function (pUrlDialogAndParams, pMethod, pBody, pContentType) {
		var vUrl = this.fUrlService+pUrlDialogAndParams;
		var vReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
		//debug("dialogSynchWithService="+vUrl);
		vReq.open(pMethod, vUrl, false, this.fUser.fAccount, this.fUser.fPassword);
		if(pBody!=null) {
			var vFile;
			try{vFile = (pBody.QueryInterface) ? pBody.QueryInterface(Components.interfaces.nsIFile) : null;}catch(e){}
			if(vFile) {
				//nsIUri source
				var vUriFrom = null;
				//nsIUri destination
				var vUriTo = null;				
				var vPersist = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Components.interfaces.nsIWebBrowserPersist);
				vPersist.saveURI(vUriFrom, null, null, null, null, vUriTo);
				//vReq.setRequestHeader("Content-Type", "application/octet-stream");
				vReq.setRequestHeader("Content-Length", vFile.fileSize);
				var vStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
				vStream.init(vFile, 1, 0, 0);
				try {
					//var vReader =  Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
					//vReader.init(vStream);
					//var vText = vReader.read(1000);
					//debug("dialogSynchWithService with file = "+vText);
					//vReq.send(vText);
					//vReader.close();
					vReq.send(vStream);
					
					//vReq.send("testcontenu");
				} finally{
					//vReader.close();
					vStream.close();
				}
			} else {
				//debug("Content-Type = "+pContentType+"  - Body = "+pBody);
				if(pContentType) vReq.setRequestHeader("Content-Type", pContentType);
				//vReq.setRequestHeader("Content-Type", pContentType || "text; charset=ISO-8859-1");//
				vReq.send(pBody);//pBody
			}
		} else {
			//debug("NoBody");
			vReq.send(null);
		}
		return vReq;
	},
	
	
	
	
	loadFromService : function (pUrlDialogAndParams, pFctCallBack, pFctCallBackError) {
		try {
			//debug("loadFromService="+pUrlDialogAndParams);
			var vUrl = this.fUrlService+pUrlDialogAndParams;
			var vReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
			//debug("ssss::"+listProperties(vReq));
			vReq.open("GET", vUrl, true, this.fUser.fAccount, this.fUser.fPassword);
			//debug("this.fUser.fAccount:: "+this.fUser.fAccount+", this.fUser.fPassword:: "+this.fUser.fPassword);
			vReq.onload = pFctCallBack;
			vReq.onerror = pFctCallBackError;
			vReq.send(null);
		} catch(e){
			//debug("rrrrr::"+this.fUrlService+" - "+this.fUser);
			debug("scHttpDataServer.loadFromService "+pUrlDialogAndParams+" : "+e);
			throw e;
		}
	},

	dialogAsynchWithService : function (pUrlDialogAndParams, pMethod, pBody, pContentType, pFctCallBack, pFctCallBackError) {
		try {
			var vUrl = this.fUrlService+pUrlDialogAndParams;
			var vReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
			vReq.open(pMethod, vUrl, true, this.fUser.fAccount, this.fUser.fPassword);
			vReq.onload = pFctCallBack;
			vReq.onerror = pFctCallBackError;
			if(pContentType) vReq.setRequestHeader("Content-Type", pContentType);
			vReq.send(pBody);
		} catch(e){
			debug("scHttpDataServer.dialogAsynchWithService "+pMethod+" - "+pUrlDialogAndParams+" : "+e);
			throw e;
		}
	},
	
	loadFromAgent : function (pIdInstance, pUrlDialogAndParams, pFctCallBack, pFctCallBackError) {
		try {
			//alert("loadFromService="+pUrlDialogAndParams);
			var vUrl = this.fUrlAgent + pIdInstance + pUrlDialogAndParams;
			var vReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
			vReq.open("GET", vUrl, true, this.fUser.fAccount, this.fUser.fPassword);
			vReq.onload = pFctCallBack;
			vReq.onerror = pFctCallBackError;
			vReq.send(null);
		} catch(e){
			debug("scHttpDataServer.loadFromAgent "+pIdInstance+" - "+pUrlDialogAndParams+" : "+e);
			throw e;
		}
	},
	
	
	dispatchUpdateUri : function (pUri, pAuthor, pSynch){
		if(pSynch) {
			this.xDispatchUpdate(pUri, pAuthor);
		} else {
			var vTimer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
			vTimer.initWithCallback(new ServerHttpDispatchUpdt(this, pUri, pAuthor), 20, 0);
		}
	},
	
	addItemListener : function (pUri, pListener){
		var vListener = this.fItemListeners[pUri];
		if(vListener){
			while(vListener.next) vListener = vListener.next;
			vListener.next = {lstn:pListener};
		} else {
			this.fItemListeners[pUri] = {lstn:pListener};
		}
	},
	
	addItemsListener : function (pListener){
		var vListener = this.fItemsListeners;
		if(vListener){
			while(vListener.next) vListener = vListener.next;
			vListener.next = {lstn:pListener};
		} else {
			this.fItemsListeners = {lstn:pListener};
		}
	},
	
	removeItemListener : function (pUri, pListener){
		var vListener = this.fItemListeners[pUri];
		var vPrevious = null;
		while(vListener && vListener.lstn != pListener) {
			vPrevious = vListener;
			vListener = vListener.next;
		}
		if(vListener) {
			if(vPrevious) {
				vPrevious.next = vListener.next;
			} else if(vListener.next){
				this.fItemListeners[pUri] = vListener.next;
			} else {
				delete this.fItemListeners[pUri];
			}
		}
	},
	
	removeItemsListener : function (pListener){
		var vListener = this.fItemsListeners;
		var vPrevious = null;
		while(vListener && vListener.lstn != pListener) {
			vPrevious = vListener;
			vListener = vListener.next;
		}
		if(vListener) {
			if(vPrevious) {
				vPrevious.next = vListener.next;
			} else {
				this.fItemsListeners = vListener.next;
			}
		}
	},
	
	fIdAuthor : 0,
	
	newIdAuthor : function(){		
		this.fIdAuthor++;
		return this.fIdAuthor;
	},
	
	
	xDispatchUpdate : function(pUri, pAuthor){
		var vItemsListener = this.fItemsListeners;
		while(vItemsListener) {
			//debug("xDispatchUpdate vItemsListener"+listProperties(vItemsListener));
			try{vItemsListener.lstn.handleUriUpdate(this, pUri, pAuthor);}catch(e){debug("Listener items:"+e);}
			vItemsListener = vItemsListener.next;
		}
		
		vItemListener = this.fItemListeners[pUri];
		while(vItemListener) {
			try{vItemListener.lstn.handleUriUpdate(this, pUri, pAuthor);}catch(e){debug("Listener item:"+e);}
			vItemListener = vItemListener.next;
		}
	},

    QueryInterface : function(pIId) {
        if (!pIId.equals(Components.interfaces.nsISupports) &&
            !pIId.equals(HTTPDATASERVER_IID))
            throw Components.results.NS_ERROR_NO_INTERFACE;
        return this;
    }
};



/* Dispatch asynchrone de l'event de modif d'une URI*/
function ServerHttpDispatchUpdt(pServer, pUri, pAuthor){
	this.fServer = pServer;
	this.fUri = pUri;
	this.pAuthor = pAuthor;
}
ServerHttpDispatchUpdt.prototype = {
	notify : function(pTimer){
		this.fServer.xDispatchUpdate(this.fUri, this.pAuthor);
	},

    QueryInterface: function(pIId) {
        if (!pIId.equals(Components.interfaces.nsISupports) &&
            !pIId.equals(Components.interfaces.nsITimerCallback))
            throw Components.results.NS_ERROR_NO_INTERFACE;
        return this;
    }
}

/* Ping régulièrement la JVM locale pour empêcher qu'elle s'arrette. */
function KeepAliveServer(pServer){
	this.fServer = pServer;
}
KeepAliveServer.prototype = {
	notify : function(pTimer){
		try{
			var vCb = function(pEvent){};
			this.fServer.dialogAsynchWithService("/u/quitter?cdaction=KeepAlive", "GET", null, null, vCb, vCb);
		} catch (e){
			debug("KeepAliveServer.notify : "+e);
		}
	},

    QueryInterface: function(pIId) {
        if (!pIId.equals(Components.interfaces.nsISupports) &&
            !pIId.equals(Components.interfaces.nsITimerCallback))
            throw Components.results.NS_ERROR_NO_INTERFACE;
        return this;
    }
}




function debug(pText){
	var vConsoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
	vConsoleService.logStringMessage(pText);
}

function listProperties (pObj){
	var vRes = "";
	var vProp = null;
	for (vProp in pObj) {
		try {
			vRes += vProp +'(' + pObj[vProp]+ ')'+ "\n";
		} catch(e){
			vRes += vProp +' -> toString in error\n';
		}
	}
	return vRes;
}




/* scHttpDataServer Module (for XPCOM registration) */
var scHttpDataServerModule = {
    registerSelf: function(compMgr, fileSpec, location, type) {
        compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
        compMgr.registerFactoryLocation(HTTPDATASERVER_CID, 
                                        "scHttpDataServer JS component", 
                                        HTTPDATASERVER_CONTRACTID, 
                                        fileSpec, 
                                        location,
                                        type);
    },

    getClassObject: function(compMgr, cid, iid) {
        if (!cid.equals(HTTPDATASERVER_CID))
            throw Components.results.NS_ERROR_NO_INTERFACE;

        if (!iid.equals(Components.interfaces.nsIFactory))
            throw Components.results.NS_ERROR_NOT_IMPLEMENTED;

        return scHttpDataServerFactory;
    },

    canUnload: function(compMgr) { return true; }
};

/* scHttpDataServer Class Factory */
var scHttpDataServerFactory = {
    createInstance: function(outer, iid) {
        if (outer != null)
            throw Components.results.NS_ERROR_NO_AGGREGATION;
    
        if (!iid.equals(HTTPDATASERVER_IID) &&
            !iid.equals(Components.interfaces.nsISupports))
            throw Components.results.NS_ERROR_INVALID_ARG;

        return new scHttpDataServer();
    }
}

/* Module initialisation */
function NSGetModule(comMgr, fileSpec) { return scHttpDataServerModule; }
