Subversion Repositories wimsdev

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.         DynAPI Distribution
  3.         IOElement SODA add-on
  4.  
  5.         The DynAPI Distribution is distributed under the terms of the GNU LGPL license.
  6.  
  7.         requires: Math, IOElement
  8. */
  9.  
  10. IOElementSoda={}; // used by dynapi.library
  11. IOElement.SODA=true;
  12.  
  13. var p=IOElement.prototype;
  14.  
  15. p.createWebService = function(name,url,fn,useSync,uid,pwd,method){
  16.         var o,IOE=IOElement;
  17.         if(typeof(fn)!='function') {
  18.                 alert('Missing or invalid Callback Function');
  19.                 return;
  20.         }
  21.        
  22.         useSync=(IOElement.SYNC)? useSync:false;       
  23.         o=this[name]={};
  24.         method=(method+'').toLowerCase();
  25.         o.sid=dynapi.functions.getGUID();
  26.         o._callback=fn;
  27.         o._name=name;
  28.         o._useSync=useSync;
  29.         o._method=(method=='post'||method=='get')? method:'post';
  30.         o._src=this; o._url=url; o._uid=uid; o._pwd=pwd;
  31.         o._iSysCall=IOE.ws_iSysCall;
  32.         o._iSysManager=IOE.ws_iSysManager;
  33.         o._iSysConnect=IOE.ws_iSysConnect;
  34.  
  35.         o.isConnected=false;
  36.         o.call=IOE.ws_callSrv;
  37.         o.getWebName=IOE.ws_getWebName;
  38.         o.getWebComment=IOE.ws_getWebComment;
  39.         o.importWebMethods=IOE.ws_importWebMethods;
  40.  
  41.         if(!useSync || (useSync && this.isSync)) o._iSysManager("connect");
  42.         else this.activateSyncMode(this+'.'+name+'._iSysManager("connect")');
  43. };
  44. p.disconnectWebService = function(name,fn){
  45.         var o=this[name];
  46.         if(o && o._src==this && o.isConnected==true){
  47.                 o._callback=fn;
  48.                 o._iSysManager("disconnect");
  49.         };
  50. };
  51. p.getResponse = function(){
  52.         var cargo=this.getCargo(true);
  53.         var retry=(this._retryID==this._cargoID)?true:false;
  54.         var response=IOElement.ws_SODAParser(this.getVariable('wsSODAResponse'));
  55.         if(retry) response.error={code:0,text:'Request Timeout'};
  56.         if(response.error) this._retryID=this._cargoID;
  57.         if(cargo) response.serviceName=cargo.DynAPIWSName;
  58.         return response;
  59. };
  60.  
  61. // WS Object Functions
  62. IOElement.wsError='Error occurred while parsing SODA Envelope';
  63. IOElement.ws_iSysManager = function(sys){
  64.         var s,r;
  65.        
  66.         this.isSync = (this._useSync && this._src.isSync)? true:false;;
  67.        
  68.         if(sys=='connect') mn='SYS:WebServiceConnect';
  69.         else if(sys=='disconnect') mn='SYS:WebServiceDisconnect';
  70.        
  71.         if(this.isSync) {
  72.                 // use sync login/logout
  73.                 r=this._iSysCall(mn);                  
  74.                 o=r.value;     
  75.                 if(o && typeof(o)=='object' && o.SYSCall==true) {
  76.                         o.error=r.error;
  77.                         r=o;s=true;
  78.                 };     
  79.                 this._iSysConnect(r,s);
  80.         }else {
  81.                 // use async login/logout
  82.                 var cargo={wsObject:this,DynAPIWSName:this._name}
  83.                 this._iSysCall(mn,null,this._iSysConnect,cargo);
  84.         }
  85. };
  86. IOElement.ws_iSysConnect = function(e,s){
  87.         var o,r,c,ws,et;
  88.  
  89.         if(!e||(e && e.constructor!=DynEvent)) {
  90.                 // sync
  91.                 o=ws=this;
  92.                 if(!e.error) c=e;
  93.                 else if(e.error) et= ((e.error.code)? e.error.code+':':'')+e.error.text;
  94.                 else if(!s) et='Connection Failed';
  95.         }else{
  96.                 // async
  97.                 o=e.getSource();
  98.                 r=o.getResponse();
  99.                 c=o.getCargo(!s||!r.value);
  100.                 o=ws=c.wsObject;
  101.                 c=r.value;
  102.                 if(r.error) et=r.error.text;
  103.         }
  104.         o.isConnected=false;
  105.         if(!et && c && (c.logout||c.login)=='failed') et='Login failed';
  106.         s=(!et && c && (c.logout||c.login)=='ok')? true:false; // web service must return a login/logout state
  107.         if(s && c.logout) {
  108.                 delete o._src[o._name];
  109.                 o.call=dynapi.functions.Null;
  110.         }else if(s && c.login){
  111.                 o._iWSName = c.name;
  112.                 o._iWSComment = c.comment;
  113.                 o._iWSMethodNames = (c.methodNames)? c.methodNames:'';
  114.                 o.isConnected=s;
  115.         }
  116.         if (o._callback) o._callback(ws,s,et);
  117. };
  118.  
  119. IOElement.ws_iSysCall=function(name,params,fn,cargo){ // used to make async/sync system call to the service
  120.         var r,o,data={};
  121.         if(this.isSync) fn=false;
  122.         data.IOResponse=(fn)? 'text/html':'text/xml';
  123.         data.IOEnvelope=IOElement.ws_createSODAEnvelope(name,params,null,null,this.sid,this._uid,this._pwd);
  124.         if(this._method=='get') r=this._src.get(this._url,data,fn,cargo);
  125.         else r=this._src.post(this._url,data,fn,cargo);
  126.         if(this.isSync) {
  127.                 // convert SODA text returned from get() or post() into response object
  128.                 if(!r.error) r=IOElement.ws_SODAParser(r.value);
  129.         }
  130.         return r;
  131. };
  132.  
  133. IOElement.ws_callSrv=function(name,params,fn,cargo){
  134.         var rt,data={IOResponse:'text/html'},cargo=(cargo)? cargo:{};
  135.         var mod=this._method;
  136.         var sync=(fn==false && this.isSync);
  137.         if(typeof(name)!='string'){
  138.                 var i,o=name;
  139.                 var na=[],pa=[];
  140.                 for(i in o){
  141.                         na[na.length]=i;
  142.                         pa[pa.length]=o[i];
  143.                 }
  144.                 name=na.join(',');
  145.                 params=pa;
  146.         }
  147.         if(typeof(params)!='object'||params==null) params=[params];
  148.         else if((params.constructor+'')!= (Array+'')) params=[params];
  149.         IOElement.ws_setStringEncFormat('xml');
  150.         cargo.DynAPIWSName=this._name;
  151.         data.IOEnvelope=IOElement.ws_createSODAEnvelope(name,params,null,null,this.sid);
  152.         if(sync) data.IOResponse = 'text/xml'; // Returned Content Format
  153.         if (mod=='get') rt=this._src.get(this._url,data,fn,cargo);
  154.         else rt=this._src.post(this._url,data,fn,cargo);
  155.         if(sync) {     
  156.                 // convert SODA text returned from get() or post() into response object
  157.                 if(!rt.error) rt = IOElement.ws_SODAParser(rt.value);          
  158.                 rt.serviceName=this._name;
  159.         }
  160.         return rt;
  161. };
  162. IOElement.ws_createSODAEnvelope = function(method,body,ecode,etext,sid,uid,pwd){
  163.         return '<envelope>'
  164.         +((sid)? '<sid>'+ sid +'</sid>':'')
  165.         +((ecode||etext)? '<err>'+ IOElement.ws_SODAStringEncode(ecode+'|'+etext) +'</err>':'')
  166.         +((uid)? '<uid>'+uid+'</uid>':'')
  167.         +((pwd)? '<pwd>'+pwd+'</pwd>':'')
  168.         +'<method>'+ IOElement.ws_SODAStringEncode(method) +'</method>'
  169.         +'<body>'+ IOElement.ws_Var2SODA(body) +'</body>'
  170.         +'</envelope>';
  171. };
  172. IOElement.ws_getWebName= function(){   
  173.         return this._iWSName;
  174. };
  175. IOElement.ws_getWebComment= function(){
  176.         return this._iWSComment;
  177. };
  178. IOElement.ws_importWebMethods = function(){    
  179.         if(!this.isSync) return false;
  180.         var fn,rt=this._iWSMethodNames;
  181.         if(rt) {
  182.                 rt=rt.split(',');
  183.                 for(var i=0;i<rt.length;i++){
  184.                         fn=rt[i];
  185.                         s = 'var mthd="'+fn+'";'
  186.                                 +'var i,params=(arguments.length)?[]:null;'
  187.                                 +'for(i=0;i<arguments.length;i++){params[i]=arguments[i]};'
  188.                                 +'return this.call(mthd,params,false);';
  189.                         this[fn]=new Function('',s);
  190.                 }
  191.                 return true;
  192.         }
  193. };
  194.  
  195. // SODA Internal Data types: U=undefined/null, I=integer, F=float, B=boolean, D=date/time, S=string, A=array, O=Object (Associative Array)
  196. IOElement._strEncFormat='xml'; // String Encode Format: html or xml
  197. IOElement.ws_Var2SODA=function(v,lvl){
  198.         var ot,ct,i,c,data,vtype=typeof(v);
  199.  
  200.         if (lvl>=0) lvl++;
  201.         else lvl=0;
  202.  
  203.         if(vtype=="number") {
  204.                 if((v+'').indexOf('.')>=0) data='<f'+lvl+'>'+v+'</f'+lvl+'>';
  205.                 else data='<i'+lvl+'>'+v+'</i'+lvl+'>';
  206.         }else if(vtype=="boolean") {
  207.                 if(v==true) data='<b'+lvl+'>true</b'+lvl+'>';
  208.                 else data='<b'+lvl+'>false</b'+lvl+'>';
  209.         }else if(vtype=="string") {
  210.                 data='<s'+lvl+'>'+this.ws_SODAStringEncode(v)+'</s'+lvl+'>';
  211.         }else if(vtype=="object" && v!=null) {
  212.                 if((v.constructor+'')==(Array+'')){
  213.                         data='<a'+lvl+'>';
  214.                         for (i=0;i<v.length;i++){
  215.                                 data+=(i>0)? '<r'+lvl+'/>'+this.ws_Var2SODA(v[i],lvl):this.ws_Var2SODA(v[i],lvl)
  216.                         }
  217.                         data+='</a'+lvl+'>';
  218.                 }else if((v.constructor+'')==(Date+'')){
  219.                         //Date format: mm/dd/yyyy hh:nn:ss
  220.                         v=((v.getMonth()+1)+'/'+v.getDate()+'/'+v.getFullYear()+' '+v.getHours()+':'+v.getMinutes()+':'+v.getSeconds());
  221.                         data='<d'+lvl+'>'+v+'</d'+lvl+'>';
  222.                 }else {
  223.                         var keys=[],values=[];
  224.                         for(var key in v){
  225.                                 values[values.length]=v[key];                          
  226.                                 if (key.indexOf('|')>=0) key=key.replace(/\|/g,'&s;');
  227.                                 keys[keys.length]=key;
  228.                         }
  229.                         v=[keys.join('|'),values];
  230.                         data='<o'+lvl+'>'+this.ws_Var2SODA(v,lvl)+'</o'+lvl+'>';
  231.                 };
  232.         }else data='<u'+lvl+'>0</u'+lvl+'>';
  233.         if (lvl==0) data='<soda>'+data+'</soda>'
  234.         return data;
  235. };
  236. IOElement.ws_SODA2Var=function(t,lvl){
  237.         var i,tag,data,elms;
  238.         var tagType,tagIndex;
  239.  
  240.         if (lvl>=0)lvl++;
  241.         else lvl=0;
  242.  
  243.         if(lvl==0) {
  244.                 if((t+'').substr(0,6)!='<soda>') return t;
  245.                 tag=IOElement.ws_getSODATag(t,'soda');
  246.                 t=tag.content;
  247.         }
  248.  
  249.         tag=this.ws_getSODATag(t);
  250.         tagType=tag.name.substr(0,1);
  251.         tagIndex=tag.name.substr(1);
  252.         if(tagType=='i') data=parseInt(tag.content);
  253.         else if(tagType=='f') data=parseFloat(tag.content);
  254.         else if(tagType=='b') data=(tag.content=='true')?true:false;
  255.         else if(tagType=='s') data=IOElement.ws_SODAStringDecode(tag.content+'');
  256.         else if(tagType=='d') data= new Date(tag.content);
  257.         else if(tagType=='a') {
  258.                 data=[];
  259.                 if(tag.content){
  260.                         elms=tag.content.split('<r'+tagIndex+'/>');
  261.                         for (i=0;i<elms.length;i++){
  262.                                 data[i]=this.ws_SODA2Var(elms[i],lvl);
  263.                         }
  264.                 }
  265.         }else if(tagType=='o') {
  266.                 data={};
  267.                 elms=this.ws_SODA2Var(tag.content,lvl)
  268.                 if(!elms) elms=[];
  269.                 var key,keys=(elms[0]+'').split('|');
  270.                 var values=elms[1];
  271.                 for (i=0;i<keys.length;i++) {
  272.                         key=keys[i];
  273.                         if(key.indexOf('&s;')>=0) key=key.replace(/\&s\;/g,'|');
  274.                         data[key]=values[i];
  275.                 }
  276.         }else if(tagType=='u') data=null;
  277.         return data;
  278. };
  279. IOElement.ws_SODAStringEncode=function (text){
  280.         if (!text) return '';
  281.         // encode string for use with html/javascript
  282.         if(this._strEncFormat=='html'){
  283.                 text=text.replace(/\\/g,"\\\\");        //  \ -> \\
  284.                 text=text.replace(/\'/g,"\\'");         // ' -> \'   "
  285.                 text=text.replace(/\n/g,"\\n");
  286.                 text=text.replace(/\r/g,"\\r");
  287.         }
  288.         // encode string for use with xml/html
  289.         text=text.replace(/\&/g,"&amp;");
  290.         text=text.replace(/</g,"&lt;");
  291.         text=text.replace(/>/g,"&gt;");
  292.         return text;
  293. };
  294. IOElement.ws_SODAStringDecode=function (text){
  295.         if (!text) return '';
  296.         text=text.replace(/\&amp\;/g,"&");
  297.         text=text.replace(/\&lt\;/g,"<");
  298.         text=text.replace(/\&gt\;/g,">");
  299.         return text;
  300. };
  301. IOElement.ws_setStringEncFormat = function(t){
  302.         this._strEncFormat=(t=='xml')? 'xml':'html';
  303. };
  304. IOElement.ws_getSODATag=function(t,n){
  305.         var st,et,tag,con;
  306.         if(!t) return {};
  307.         n=(n)?n:'';
  308.         st=t.indexOf('<'+n);
  309.         et=t.indexOf('>',st);
  310.         if(st || et) {
  311.                 tag=t.substr(st+1,(et-1)-st);
  312.                 st=et+1;
  313.                 et=t.indexOf('</'+tag+'>');
  314.                 con=t.substr(st,et-st)
  315.  
  316.         }
  317.         return {name:tag,content:con};
  318. };
  319. IOElement.ws_SODAParser=function(envelope){
  320.         var r={
  321.                 error:IOElement.ws_SODAStringDecode(IOElement.ws_getSODATag(envelope,'err').content),
  322.                 methodName:IOElement.ws_SODAStringDecode(IOElement.ws_getSODATag(envelope,'method').content),
  323.                 value:IOElement.ws_SODA2Var(IOElement.ws_getSODATag(envelope,'body').content)
  324.         };
  325.         if(r.error) {
  326.                 var ea=r.error.split('|');
  327.                 r.error={code:ea[0],text:ea[1]};
  328.         }else if((envelope+'').indexOf('<envelope>')!=0){
  329.                 r.error={code:'E3',text:IOElement.wsError+':\n\n'+envelope};
  330.         };
  331.         return r;
  332. };
  333.