webservice.js

Summary

This is a library used by javascript webservice adapters generated by o4glwsdl2js.html.

XMLHttpRequest object is used to call the webservice operations. You can test the browser compatibility with the xmlHttpRequest property that is included in every webservice adapter, this property is set to false if no implementation is found.

This file is part of the Open 4GL webservices project.



Version: 0.1

Author: Lic. Edgar Medrano Pérez edgarmedrano@gmail.com


Class Summary
__Request  
__Response  
__WebService  

Method Summary
static Object __WebService_getXMLHttp()
           Gets a new instance of the XMLHttpRequest object.

/*------------------------------------------------------------------------
  File:        o4glwsdl2js.js
  Description: This is a library used by javascript webservice adapters
               generated by o4glwsdl2js.html
  Author:      Lic. Edgar Medrano Pérez 
               edgarmedrano@gmail.com
  Created:     2006.03.04
  Company:     Open 4GL webservices project
               http://o4glws.sourceforge.net
  Notes:       XMLHttpRequest object is used to call the webservice
               operations. You can test the browser compatibility with
			   the xmlHttpRequest property that is included in every 
			   webservice adapter, this property is set to false if no 
			   implementation is found.
------------------------------------------------------------------------*/

/** 
 * @fileoverview This is a library used by javascript webservice adapters
 * generated by o4glwsdl2js.html.
 * <p>XMLHttpRequest object is used to call the webservice operations. 
 * You can test the browser compatibility with the xmlHttpRequest 
 * property that is included in every webservice adapter, this property 
 * is set to false if no implementation is found.</p>
 * <p>This file is part of the 
 * {@link http://o4glws.sourceforge.net/ Open 4GL webservices project}.</p>
 * @author Lic. Edgar Medrano Pérez edgarmedrano@gmail.com
 * @version 0.1 
 */

/**
 * Removes the namespace.
 * @param {String} name The attribute/tag name.
 * @return {String} the clean name.
 */
function cleanName(name) {
	return (name.indexOf(":") >= 0) ? name.substr(name.indexOf(":") + 1) : name;
}	

/**
 * Finds the nodes that match the specified path.
 * @param {Object} node XML parent node.
 * @param {String} path Path to child node. Example: "service/port/address"
 * @param {int} depth This parameter is for internal use only; don´t include
                      it in your call.
 * @return {Array} An array containing the found nodes.
 */
function xpath(node,path,depth) {
	var arrpath;
	var result = new Array();
	
	if(node && path) {
		arrpath = path.split("/");
		if(!depth) { 
			depth = 0;
		}
		
		for(var i = 0; i < node.childNodes.length; i ++) {
			if(cleanName(node.childNodes[i].nodeName) == arrpath[depth]) {
				if(depth < arrpath.length - 1) {
					return xpath(node.childNodes[i],path,depth + 1);  
				} else {
					result[result.length] = node.childNodes[i];
				}
			}
		}
	}
	
	return result;
}

/**
 * This is the abstract definition of a webservice adapter.
 * @param {String} urn The webservice name.
 * @param {String} url The url pointing to the webservice deployment location.
 * @constructor
 */
function __WebService(urn,url) {
   this.urn = urn;
   this.url = url;
   this.security = false;
   this.username = "";
   this.password = "";
   this.digest = false;
   this.xmlHttpRequest = __WebService_getXMLHttp();
   this.invoke = __WebService_invoke;
   this.setSecurity = __WebService_setSecurity;
}

/**
 * Sets the parameters to use in the security header, if this parameters aren't 
 * set the security header wouldn´t be included in the request.
 * @param {String} username The username to be included in the UsernameToken.
 * @param {String} password The password to be included in the UsernameToken.
 * @param {boolean} digest <pre>true</pre> - to encrypt the password <br>.
 *                         <pre>false</pre> - <em>(default)</em> don't encrypt the password
 */
function __WebService_setSecurity(username,password,digest) {
   this.security = (username != "");
   this.username = username;
   this.password = password;
   if(digest) {
     this.digest = true;
   } else {
     this.digest = false;
   }
}

/**
 * Gets a new instance of the XMLHttpRequest object.
 * @return {Object} The instance of the XMLHttpRequest object.
 */
function __WebService_getXMLHttp(){
	var xmlhttp = false;
	
	/*@cc_on @*/ 
	/*@if (@_jscript_version >= 5) 
	// JScript gives us Conditional compilation, we can cope with old IE versions. 
	// and security blocked creation of the objects. 
	  try { 
	  xmlhttpType="Msxml2.XMLHTTP";
	  xmlhttp = new ActiveXObject(xmlhttpType); 
	  
	  } catch (e) { 
	   try { 
		xmlhttpType="Microsoft.XMLHTTP";
		xmlhttp = new ActiveXObject(xmlhttpType); 
	   } catch (E) { 
		xmlhttp = false; 
	   } 
	  } 
	@end @*/ 
	
	if (!xmlhttp && typeof XMLHttpRequest!='undefined') { 
	  xmlhttpType="XMLHttpRequest";
	  xmlhttp = new XMLHttpRequest(); 
	} 
	
	return xmlhttp;
}

/**
 * Calls a webservice operation using the XMLHttpRequest object.
 * @param {__Request} request Webservice request.
 * @param {String} message The operation to be called.
 * @param {Function} callback The function to be used as a callback to handle
 *                            the response.
 */
function __WebService_invoke(request,message,callback) {
    var xmlhttp = this.xmlHttpRequest;
	var objRef = this;
    xmlhttp.open("POST", this.url); 	
	xmlhttp.setRequestHeader("Cache-Control","must-revalidate"); 
    xmlhttp.setRequestHeader("Content-Type","text/xml; charset=utf-8");	
    xmlhttp.onreadystatechange = function() { 
		if (xmlhttp.readyState == 4) {
			if (xmlhttp.status == 200) {
				var response = new __Response(xmlhttp.responseXML,message);
				eval("objRef." + callback + "(request,response)"); 
			} else {
				var response = new __Response(null,message);
				eval("objRef." + callback + "(request,response)"); 
				//alert("web service response error:" + xmlhttp.status + "," + xmlhttp.statusText);
			}
		}  
    } 
    xmlhttp.send(request.toXML(this)); 
}

/**
 * Defines a webservice request. One of this must be created for every call to
 * a webservice operation. 
 * @param {String} urn The webservice name.
 * @param {String} method The operation name to be called.
 * @constructor
 */
function __Request(urn,method) {
	this.urn = urn;
	this.method = method;
	this.params = new Object();
	this.addParam = function (name,value) {
	   this.params[name] = value;
	};
	this.getParam = function (name) {
	   return this.params[name];
	};
	
	this.paramXML = __Request_paramXML;
	this.toXML = __Request_toXML;
}

/**
 * Generate the XML code of a single request parameter.
 * @param {String} name This is used as the tagname.
 * @param value The parameter value,
 * @return {String} The XML code.
 */
function __Request_paramXML(name,value) {
	var result = "";
	var i;
	var field;
	var strAux;
	
	if(typeof(value) != "undefined") {
		if(value.constructor == Array) {
			result += "<" + name + ">"; 
			for(i=0; i<value.length; i++) {
				result += this.paramXML(value.type, value[i]);
			}
			result += "</" + name + ">";
		} else {
		    if(value.constructor == Date) {
				result += "<" + name + ">"; 
				result += value.getFullYear() + "-";
				strAux = "0" + value.getMonth();
				result += strAux.substr(0,2) + "-";
				strAux = "0" + value.getDate();
				result += strAux.substr(0,2);
				result += "</" + name + ">";
		    } else {
			    if(typeof(value) == "object") {
				    result += "<" + name + ">";
					for(field in value) {
						result += this.paramXML(field,value[field]);
					}
				    result += "</" + name + ">";
				} else {
					result += "<" + name + ">" + value + "</" + name + ">";
				}
			}
		}
    } else {
		result += "<" + name + " />";
	}	
	
	return result;
}

/**
 * Generate the XML code for the whole request.
 * @param {__Webservice} wservice Reference to the webservice adapter 
                         that's making the call.
 * @return {String} The XML code.
 */
function __Request_toXML(wservice) {
	var result;
    var param;
    result = '<?xml version="1.0" encoding="utf-8"?>'+
		"<soap:Envelope"+
		  ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'+
		  ' xmlns:xsd="http://www.w3.org/2001/XMLSchema" '+
		  ' xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">';
		  
	if(wservice.security) {
	    var datCreated = new Date();
	    var datExpires = new Date();
		var strNonce = "";
		var strPassword = wservice.password;
		var strPasswordType = "PasswordText";
	    var strCreated;
	    var strExpires;
		var strAux;
		
		datCreated.setHours(datCreated.getHours() + datCreated.getTimezoneOffset() / 60);
		datExpires.setHours(datExpires.getHours() + datExpires.getTimezoneOffset() / 60);
		datExpires.setMinutes(datExpires.getMinutes() + 5);
			
		strCreated = datCreated.getFullYear() + "-";
		strAux = "0" + datCreated.getMonth();
		strCreated += strAux.substr(0,2) + "-";
		strAux = "0" + datCreated.getDate();
		strCreated += strAux.substr(0,2) + "T";
		strAux = "0" + datCreated.getHours();
		strCreated += strAux.substr(0,2) + ":";
		strAux = "0" + datCreated.getMinutes();
		strCreated += strAux.substr(0,2) + ":";
		strAux = (datCreated.getSeconds() < 10 ? "0" : "") 
		   + (datCreated.getSeconds() + (datCreated.getMilliseconds() / 1000))
		   + (datCreated.getMilliseconds() > 0 ? "" : ".000");
		strCreated += strAux.substr(0,2) + "Z";

		strExpires = datExpires.getFullYear() + "-";
		strAux = "0" + datExpires.getMonth();
		strExpires += strAux.substr(0,2) + "-";
		strAux = "0" + datExpires.getDate();
		strExpires += strAux.substr(0,2) + "T";
		strAux = "0" + datExpires.getHours();
		strExpires += strAux.substr(0,2) + ":";
		strAux = "0" + datExpires.getMinutes();
		strExpires += strAux.substr(0,2) + ":";
		strAux = (datExpires.getSeconds() < 10 ? "0" : "") 
		   + (datExpires.getSeconds() + (datExpires.getMilliseconds() / 1000))
		   + (datExpires.getMilliseconds() > 0 ? "" : ".000");
		strExpires += strAux.substr(0,2) + "Z";
		
		if(wservice.digest) {
			strNonce = wservice.getNonce();
			strPassword = wservice.encode(strPassword,strNonce);
		    strPasswordType = "PasswordDigest";
		}
		
		result += 
			'<soap:Header>'+
			  '<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soap:mustUnderstand="1">'+
			    '<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">'+
			      '<wsu:Created>' + strCreated + '</wsu:Created>'+
			      '<wsu:Expires>' + strExpires + '</wsu:Expires>'+ 
			    '</wsu:Timestamp>'+
			    '<wsse:UsernameToken>'+
			      '<wsse:Username>' + wservice.username + '</wsse:Username>'+ 
			      '<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#' + strPasswordType + '">' + strPassword + '</wsse:Password>'+ 
			      '<wsse:Nonce>' + strNonce + '</wsse:Nonce>'+ 
			      '<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">' + strCreated + '</wsu:Created>'+ 
			    '</wsse:UsernameToken>'+
			  '</wsse:Security>'+
			'</soap:Header>';
	}	  
		  
	result += 
	      '<soap:Body><' + this.method +
		  ' xmlns="urn:' + this.urn + '"'+
		  '>'; 
		  
    for(param in this.params) {
	   result += this.paramXML(param,this.params[param]);
	}
	result +=
		  '</' + this.method + '>'+
		'</soap:Body></soap:Envelope>';	
		
	return result;
}

/**
 * Handles the webservice response. One of this will be created for every 
 * call to a webservice operation. 
 * @param {Object} xml The xml document returned by the webservice.
 * @param {String} message The operation name just being called.
 * @constructor
 */
function __Response(xml,message) {
    var fault = xpath(xml,"Envelope/Body/Fault")[0];
	if(fault) {
	   this.fault = new Object();
	   this.fault.faultcode = xpath(fault,"faultcode")[0];
	   this.fault.faultstring = xpath(fault,"faultstring")[0];
	   this.fault.faultactor = xpath(fault,"faultactor")[0];
	   this.fault.faultcode = this.fault.faultcode ? this.fault.faultcode.firstChild.nodeValue : "";
	   this.fault.faultstring = this.fault.faultstring ? this.fault.faultstring.firstChild.nodeValue : "";
	   this.fault.faultactor = this.fault.faultactor ? this.fault.faultactor.firstChild.nodeValue : "";
	}
	this.params = xpath(xml,"Envelope/Body/" + message)[0];
	this.getParam = __Response_getParam;
	this.xmlToObject = __Response_xmlToObject;
}

/**
 * Builds an object by parsing the given xml node.
 * @param {Object} node The xml node containing the object.
 * @return {Object} The object.
 */
function __Response_xmlToObject(node) {
	var result = new Object();
	
	for(var i = 0; i < node.childNodes.length;i++) {
		if(node.childNodes[i].firstChild) { 
			if(node.childNodes[i].firstChild.nodeType == 3 /*Text*/) {
				result[node.childNodes[i].nodeName] = node.childNodes[i].firstChild.nodeValue;
			} else {
			    result[node.childNodes[i].nodeName] = this.xmlToObject(node.childNodes[i]);
			}
		} else {
			result[node.childNodes[i].nodeName] = "";
		}
	}
	
	return result;
}

/**
 * Gets a response parameter.
 * @param {String} name The parameter's name.
 * @param {String} type The parameter's type.
 * @return The parameter's value.
 */
function __Response_getParam(name,type) {
   var param;
   var node;
   
   if(node = xpath(this.params,name)) {
	   if(node[0]) {
		   node = node[0];
		   if(type == "Array") {
			  param = new Array();
			  for(var i = 0; i < node.childNodes.length;i++) {
				 if(node.childNodes[i].firstChild) { 
				    if(node.childNodes[i].firstChild.nodeType == 3 /*Text*/) {
						param[i] = node.childNodes[i].nodeValue;
					} else {
					    param[i] = this.xmlToObject(node.childNodes[i]);
					}
				 } else {
					param[i] = node.childNodes[i].nodeValue;
				 }
			  }
		   } else if(type == "Object") {
			 param = xmlToObject(node);
		   } else {
			 param = node.nodeValue;
		   }
	   }
   }
   
   return param;
}


Documentation generated by JSDoc on Sun Apr 16 18:38:12 2006