[ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
1 /* 2 Copyright (c) 2003-2004 Jan-Klaas Kollhof 3 4 This file is part of the JavaScript o lait library(jsolait). 5 6 jsolait is free software; you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as published by 8 the Free Software Foundation; either version 2.1 of the License, or 9 (at your option) any later version. 10 11 This software is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public License 17 along with this software; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 /** 22 Provides an JSON-RPC imlementation. 23 */ 24 Module("jsonrpc", "0.3.2", function(mod){ 25 26 var lang = importModule("lang"); 27 var tokens = lang.tokens; 28 29 var ObjectBuffer=Class("ObjectBuffer", function(publ, supr){ 30 publ.init=function(){ 31 this.data=""; 32 } 33 publ.getObjects=function(data){ 34 this.data += data; 35 var t = new lang.Tokenizer(this.data); 36 var brCnt= 0; 37 var objects = []; 38 var readCnt = 0 39 while(! t.finished()){ 40 var n = t.next(); 41 if(n.type != tokens.ERR){ 42 if(n.value == "{"){ 43 brCnt+=1; 44 }else if(n.value == "}"){ 45 brCnt-=1; 46 if(brCnt==0){ 47 var s = this.data.slice(readCnt, n.pos+1); 48 readCnt += s.length; 49 objects.push(s); 50 } 51 } 52 }else{ 53 break; 54 } 55 } 56 this.data = this.data.slice(readCnt); 57 return objects; 58 } 59 }) 60 61 var nameAllowed=function(name){ 62 return name.match(/^[a-zA-Z]\w*$/) != null; 63 } 64 65 var getMethodByName=function(obj, name){ 66 try{//to get a method by asking the service 67 obj = obj._getMethodByName(name) 68 }catch(e){ 69 var names = name.split("."); 70 for(var i=0;i<names.length;i++){ 71 name = names[i]; 72 if(nameAllowed(name)){ 73 obj = obj[name]; 74 } 75 } 76 } 77 return obj; 78 } 79 80 var Response=Class("Response", function(publ, supr){ 81 publ.init=function(id, result, error){ 82 this.id=id; 83 this.result = result; 84 this.error = error; 85 } 86 publ._toJSON=function(){ 87 var p = [lang.objToJson(this.id), lang.objToJson(this.result),lang.objToJson(this.error)]; 88 return '{"id":' + p[0] + ', "result":' + p[1] + ', "error":' + p[2] + "}"; 89 } 90 }) 91 92 var Request=Class("Request", function(publ, supr){ 93 publ.init=function(id, method, params){ 94 this.id=id; 95 this.method = method; 96 this.params = params; 97 } 98 publ._toJSON=function(){ 99 var p = [lang.objToJson(this.id), lang.objToJson(this.method),lang.objToJson(this.params)]; 100 return '{"id":' + p[0] + ', "method":' + p[1] + ', "params":' + p[2] + "}"; 101 } 102 }) 103 104 var Notification=Class("Notification", function(publ, supr){ 105 publ.init=function(method, params){ 106 this.method = method; 107 this.params = params; 108 } 109 publ._toJSON=function(){ 110 var p = [lang.objToJson(this.method),lang.objToJson(this.params)]; 111 return '{"method":' + p[0] + ', "params":' + p[1] + "}"; 112 } 113 }) 114 115 var ResponseHandler=Class("ResponseHandler", function(publ, supr){ 116 publ.init=function(callback){ 117 this.callback=callback; 118 } 119 publ.handleResponse=function(resp){ 120 this.callback(resp.result, resp.error); 121 } 122 }) 123 124 var RPCLib = Class("RPCLib", function(publ, supr){ 125 126 }) 127 128 var BaseConnectionHandler = Class("BaseConnectionHandler", function(publ, supr){ 129 publ.init=function(service){ 130 this.service = service; 131 this.jsonParser = new lang.JSONParser(); 132 this.jsonParser.addLib(new RPCLib(), "rpc", []); 133 this.respHandlers = []; 134 this.objBuffer = new ObjectBuffer(); 135 } 136 137 publ.addResponseHandler=function(cb){ 138 var id=1; 139 while(this.respHandlers[""+id] ){ 140 id+=1; 141 } 142 id="" + id; 143 this.respHandlers[id] = new ResponseHandler(cb); 144 return id; 145 } 146 147 publ.send = function(data){ 148 } 149 150 publ.sendNotify = function(name, args){ 151 var n = new Notification(name, args); 152 n = this.jsonParser.objToJson(n); 153 this.send(n) 154 } 155 156 publ.sendRequest = function(name, args, callback){ 157 var id = this.addResponseHandler(callback); 158 var r = new Request(id, name, args); 159 r = this.jsonParser.objToJson(r); 160 this.send(r); 161 } 162 163 publ.sendResponse = function(id, result, error){ 164 var r = new Response(id, result, error); 165 r = this.jsonParser.objToJson(r); 166 this.send(r); 167 } 168 169 publ.handleRequest = function(req){ 170 var name = req.method; 171 var params = req.params; 172 var id=req.id; 173 if(this.service[name]){ 174 try{ 175 var rslt = this.service[name].apply(this.service,params); 176 this.sendResponse(id, rslt, null) 177 }catch(e){ 178 this.sendResponse(id, null, new ApplicationError("" + e)) 179 } 180 }else{ 181 this.sendResponse(id, null, new MethodNotFound()); 182 } 183 } 184 185 publ.handleNotification = function(notif){ 186 if(this.service[notif.method]){ 187 try{ 188 this.service[notif.method].apply(this.service, notif.params); 189 }catch(e){ 190 } 191 } 192 } 193 194 publ.handleResponse = function(resp){ 195 var id=resp.id; 196 var h = this.respHandlers[id]; 197 h.handleResponse(resp) 198 delete this.respHandlers[id] 199 } 200 201 publ.handleData = function(data){ 202 var objs = this.objBuffer.getObjects(data); 203 for(var i=0;i<objs.length;i++){ 204 try{ 205 var obj = this.jsonParser.jsonToObj(objs[i]); 206 }catch(e){ 207 throw "Not well formed"; 208 } 209 if(obj.method != null){ 210 if(obj.id != null){ 211 this.handleRequest(new Request(obj.id, obj.method, obj.params)); 212 }else{ 213 this.handleNotification(new Notification(obj.method, obj.params)); 214 } 215 }else if(obj.id != null){ 216 this.handleResponse(new Response(obj.id, obj.result, obj.error)); 217 }else{ 218 throw "Unknown Data"; 219 } 220 } 221 } 222 }) 223 224 var SocketConnectionHandler = Class("SocketConnectionHandler", BaseConnectionHandler, function(publ, supr){ 225 publ.init=function(socket, localService){ 226 this.socket = socket; 227 socket.addEventListener("connectionData", this, false); 228 supr(this).init( localService); 229 } 230 231 publ.handleEvent=function(evt){ 232 this.handleData(evt.data); 233 } 234 235 publ.send=function(data){ 236 this.socket.send(data); 237 } 238 239 publ.close=function(data){ 240 this.socket.close(); 241 } 242 }) 243 244 var HTTPConnectionHandler = Class("HTTPConnectionHandler", BaseConnectionHandler, function(publ, supr){ 245 var urllib; 246 publ.init=function(url, localService){ 247 urllib=importModule("urllib"); 248 this.url = url; 249 supr(this).init( localService); 250 } 251 252 publ.handleData = function(data){ 253 try{ 254 var obj = this.jsonParser.jsonToObj(data); 255 }catch(e){ 256 throw "Not well formed"; 257 } 258 if(obj.id != null){ 259 return obj; 260 }else{ 261 throw "Unknown Data (No id property found)"; 262 } 263 } 264 265 publ.sendRequest = function(name, args, callback){ 266 var sync = false; 267 if(typeof callback != "function"){//see if it is sync 268 args.push(callback); 269 sync=true; 270 } 271 var data = new Request("httpReq", name, args); 272 data = this.jsonParser.objToJson(data); 273 if(sync){ 274 var rsp = urllib.postURL(this.url, data, [["Content-Type", "text/plain"]]); 275 rsp = this.handleData(rsp.responseText); 276 if(rsp.error){ 277 throw rsp.error; 278 }else{ 279 return rsp.result; 280 } 281 }else{//async connection uses the respHandler to handle the repsonse 282 var self = this; 283 urllib.postURL(this.url, data, [["Content-Type", "text/plain"]], function(rsp){ 284 try{ 285 rsp = self.handleData(rsp.responseText); 286 }catch(e){ 287 callback(null,e); 288 return; 289 } 290 callback(rsp.result, rsp.error); 291 }); 292 } 293 } 294 295 publ.sendNotify = function(name, args){ 296 var data = new Notification(name, args); 297 data = this.jsonParser.objToJson(data); 298 urllib.postURL(this.url, data, [["Content-Type", "text/plain"]], function(rsp){}); 299 } 300 }) 301 302 var PeerObject=Class("PeerObject", function(publ, supr){ 303 publ.init=function(name, conn){ 304 var fn=function(){ 305 var args=[]; 306 for(var i=0;i<arguments.length;i++){ 307 args[i] = arguments[i]; 308 } 309 var cb=args.pop(); 310 return conn.sendRequest(name, args, cb); 311 } 312 return fn; 313 } 314 }) 315 316 var PeerNotifyObject=Class("PeerNotifyObject", function(publ, supr){ 317 publ.init=function(name, conn){ 318 var fn=function(){ 319 var args=[]; 320 for(var i=0;i<arguments.length;i++){ 321 args[i] = arguments[i]; 322 } 323 conn.sendNotify(name, args); 324 } 325 return fn; 326 } 327 }) 328 329 var BasePeer = Class("BasePeer", function(publ, supr){ 330 publ.init=function(conn, methodNames){ 331 this._conn = conn; 332 this.notify = new PeerObject("notify", conn); 333 this._add(methodNames); 334 } 335 336 var setupPeerMethod=function(root, methodName, conn, MethClass){ 337 var names = methodName.split("."); 338 var obj = root; 339 for(var n=0;n<names.length-1;n++){ 340 var name = names[n]; 341 if(obj[name]){ 342 obj = obj[name]; 343 }else{ 344 obj[name] = new Object(); 345 obj = obj[name]; 346 } 347 } 348 var name = names[names.length-1]; 349 if(obj[name]){ 350 }else{ 351 var mth = new MethClass(methodName, conn); 352 obj[name] = mth; 353 } 354 } 355 356 publ._add = function(methodNames){ 357 for(var i=0;i<methodNames.length;i++){ 358 setupPeerMethod(this, methodNames[i], this._conn, PeerObject); 359 setupPeerMethod(this.notify, methodNames[i], this._conn, PeerNotifyObject); 360 } 361 } 362 }) 363 364 365 mod.ServiceProxy = Class("ServiceProxy", BasePeer, function(publ, supr){ 366 publ.init = function(url, methodNames, localService){ 367 var n = url.match(/^jsonrpc:\/\/(.*:\d*)$/); 368 if(n!=null){//is it json-rpc over TCP protocoll 369 var hostaddr = n[1]; 370 try{ 371 var socket = createConnection(); 372 }catch(e){ 373 throw "Can't create a socket connection." 374 } 375 socket.connect(hostaddr); 376 supr(this).init( new SocketConnectionHandler(socket, localService), methodNames); 377 }else{//or is it json-rpc over http 378 supr(this).init( new HTTPConnectionHandler(url, localService), methodNames); 379 } 380 } 381 }) 382 }) 383
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 17:20:01 2007 | par Balluche grâce à PHPXref 0.7 |