function AJAX(url,metodo,params,processa,modo,Header,separador) {
	this.url       = url;
	this.metodo    = (metodo) ? metodo : 'GET';
	this.params    = (this.metodo == 'GET') ? null : params;
	this.processaResultado = processa;
	this.Header    = new Array();
	this.modo      = (modo) ? modo : 'T';
	this.separador = (separador) ? separador : '&';
	this.assinc = true;
	this.contadorSolicitacoes = 0;
	this.qtdSolicitacoes = 3;
	this.podeNulo = false;
	this.debugarJS = false;
}

AJAX.prototype = {
    //Adiciona um cabeçalho na requisição
	addHeader: function(h,v) {
		this.Header[h] = v;
	},
	
	//Exclui o cabeçalho 
	delHeader: function(h) {
		delete(this.Header[h]);
	},
	
    //Seta o cabeçalho na requisição
	setHeader: function() {
		if(this.httpRequest==null) { return;} 
		for(h in this.Header) {
			this.httpRequest.setRequestHeader(h,this.Header[h]);
		}
	},
	
	getResponseHeader: function(h){
		return this.httpRequest.getResponseHeader(h);
	},
	
	abort: function(){
		this.httpRequest.abort();
	},
	
	//Conecta com o servidor
	conectar: function() {
		this.onbeforeconectar();
		
		if(this.url==undefined||this.url=='') { return; }
		
		this.httpRequest = null;
		if (window.XMLHttpRequest) { // Mozilla, Safari,...
			this.httpRequest = new XMLHttpRequest();
		} else if (window.ActiveXObject) { // IE
			try {
				this.httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
				try {
					this.httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (e) {}
			}
		}
		if(this.httpRequest!=null&&this.httpRequest!=undefined) {
			var obj = this;
			this.httpRequest.onreadystatechange = function() {
				try{
					obj.onreadystatechange();
				} catch(e) {
					obj.abort();
					obj.onerror(e);
				}
			}
			this.metodo = this.metodo.toUpperCase();
			
			if(this.debugarJS){
				if(this.metodo == "GET") this.params = "";
				this.metodo = "POST";
				var trace = arguments.callee.trace();
				this.params += "debugBacktraceJS="+trace.join("\n");
			}
			
			if(this.metodo==undefined||this.metodo=='') { this.metodo = 'GET';}
			if(this.metodo == "POST"){
				this.addHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
			}
			this.httpRequest.open(this.metodo,this.url, this.assinc);
			this.setHeader();
			this.httpRequest.send(this.params);
		}
	},
	
	onreadystatechange: function(){
		this.processaRetorno();
	},
	
	onerror: function(e){
		//nada
	},
	
	onbeforeconectar: function(){
		//nada
	},
	
	//Manipula os dados vindos do servidor						
	processaRetorno: function() {
		if(this.httpRequest.readyState==4){
			if(this.httpRequest.status==200){
				if((this.modo!='T')&&(this.modo!='X')&&(this.modo!='A')&&(this.modo!='O')){
					this.modo = 'T';
				}
				
				var resp = ((this.modo == 'T' )||(this.modo == 'A')||(this.modo == 'O')) ?  this.httpRequest.responseText : this.httpRequest.responseXML;
				
				if(this.contadorSolicitacoes < this.qtdSolicitacoes){
					if(this.podeNulo || resp){
						this.contadorSolicitacoes = 0;
						
						if((this.processaResultado != null)&&(this.modo == 'T')){
							this.processaResultado(resp);
						}else if((this.processaResultado != null)&&(this.modo == 'A')){
							this.processaModoArray(resp);
						}else if((this.processaResultado != null)&&(this.modo == 'X')){
							this.processaResultado(resp);
						}else if((this.processaResultado != null)&&(this.modo == 'O')){
							this.processaModoObjeto(resp);
						}else{
							document.write(resp) + 'Escopo de Saida em Caso de Erro no modo da Função';
						}
					} else {
						this.contadorSolicitacoes++;
						this.abort();
						this.conectar();
					}
				} else {
					this.contadorSolicitacoes = 0;
					throw new Exception(1, "Valor de retorno nulo", "O servidor enviou uma resposta nula para a requisição "+this.url);
				}
			} else {
				throw new Exception(this.httpRequest.status, "HTTP Error", this.httpRequest.statusText + ' :-> ' + this.url);
			}
		}
	},
	
	//Manipula o resultado e joga num Array
	processaModoArray: function(retorno){
		var strRetorno   = retorno;
		var strSeparador = new String(this.separador);
		var arrayRetorno = strRetorno.split(strSeparador);        
		this.processaResultado(arrayRetorno);        
	},						

	//Manipula o resultado e joga num Objeto Array;
	processaModoObjeto: function(retorno){
		var strRetorno   = retorno;
		var strSeparador = new String(this.separador);
		var arrayRetorno = strRetorno.split(strSeparador);              
		this.retorno = new Array();
		
		for (i = 0; i < arrayRetorno.length;i++){
			var val = arrayRetorno[i].split('->');
			this.retorno[val[0]] = val[1];
		}
		this.processaResultado(this);        
	}
}

function Exception(cod, nome, mensagem){
	this.cod = cod;
	this.name = nome;
	this.message = mensagem;
	
	this.toString = function(){
		return "#"+this.cod+" - "+this.name+" ["+this.message+"]";
	}
}
Function.prototype.trace = function(){
	var trace = [];
	var current = this;
	while(current)
	{
		trace.push(current.signature());
		current = current.caller;
	}
	return trace;
}

Function.prototype.signature = function(){
	var signature = {
		name: this.getName(),
		params: [],
		toString: function()
		{
			var params = this.params.length > 0 ? 
				"'" + this.params.join("', '") + "'" : "";
			return this.name + "(" + params + ")"
		}
	};
	if(this.arguments)
	{
		for(var x=0; x<this.arguments.length; x++)
			signature.params.push(this.arguments[x]);
	}
	return signature;
}

Function.prototype.getName = function(){
	if(this.name)
		return this.name;
	var definition = this.toString().split("\n")[0];
	return this;
	var exp = /^function ([^\s(]+).+/;
	if(exp.test(definition))
		return definition.split("\n")[0].replace(exp, "$1") || "anonymous";
	return "anonymous";
}