blob: f048dbffd248f2d7017c10455db6fe612b540f71 [file] [log] [blame]
T Jake Luciani322caa22010-02-15 03:24:55 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19var Thrift = {
20
21 Type : {
22 "STOP" : 0,
23 "VOID" : 1,
24 "BOOL" : 2,
25 "BYTE" : 3,
26 "I08" : 3,
27 "DOUBLE" : 4,
28 "I16" : 6,
29 "I32" : 8,
30 "I64" : 10,
31 "STRING" : 11,
32 "UTF7" : 11,
33 "STRUCT" : 12,
34 "MAP" : 13,
35 "SET" : 14,
36 "LIST" : 15,
37 "UTF8" : 16,
38 "UTF16" : 17
39 },
40
41 MessageType : {
42 "CALL" : 1,
43 "REPLY" : 2,
44 "EXCEPTION" : 3
45 }
46}
47
48Thrift.TException = {}
49Thrift.TException.prototype = {
50 initialize: function( message, code ) {
51 this.message = message;
52 this.code = (code == null) ? 0 : code;
53 }
54}
55
56
T Jake Lucianiefabb892010-07-28 22:31:12 +000057Thrift.TApplicationExceptionType = {
T Jake Luciani322caa22010-02-15 03:24:55 +000058 "UNKNOWN" : 0,
59 "UNKNOWN_METHOD" : 1,
60 "INVALID_MESSAGE_TYPE" : 2,
61 "WRONG_METHOD_NAME" : 3,
62 "BAD_SEQUENCE_ID" : 4,
63 "MISSING_RESULT" : 5
64}
65
66Thrift.TApplicationException = function(message, code){
67 this.message = message
68 this.code = (code == null) ? 0 : code
69}
70
71Thrift.TApplicationException.prototype = {
72
73 read : function(input){
74
75 var ftype
76 var fid
77 var ret = input.readStructBegin(fname)
78
79 this.fname = ret.fname
80
81 while(1){
82
83 ret = input.readFieldBegin()
84
85 if(ret.ftype == TType.STOP)
86 break
87
88 var fid = ret.fid
89
90 switch(fid){
91 case 1:
92 if( ret.ftype == Type.STRING ){
93 ret = input.readString()
94 this.message = ret.value
95 } else {
96 ret = input.skip(ret.ftype)
97 }
98
99 break
100 case 2:
101 if( ret.ftype == Type.I32 ){
102 ret = input.readI32()
103 this.code = ret.value
104 } else {
105 ret = input.skip(ret.ftype)
106 }
107 break
108
109 default:
110 ret = input.skip(ret.ftype)
111 break
112 }
113
114 input.readFieldEnd()
115
116 }
117
118 input.readStructEnd()
119
120 },
121
122 write: function(output){
123 var xfer = 0;
124
125 output.writeStructBegin('TApplicationException');
126
127 if (this.message) {
128 output.writeFieldBegin('message', Type.STRING, 1)
129 output.writeString(this.getMessage())
130 output.writeFieldEnd()
131 }
132
133 if (this.code) {
134 output.writeFieldBegin('type', Type.I32, 2)
135 output.writeI32(this.code)
136 output.writeFieldEnd()
137 }
138
139 output.writeFieldStop()
140 output.writeStructEnd()
141
142 },
143
144 getCode : function() {
145 return this.code
146 },
147
148 getMessage : function() {
149 return this.message
150 }
151}
152
153
154
155/**
156 *If you do not specify a url then you must handle ajax on your own.
157 *This is how to use js bindings in a async fashion.
158 */
159Thrift.Transport = function(url){
160 this.url = url
161 this.wpos = 0
162 this.rpos = 0
163
164 this.send_buf = ''
165 this.recv_buf = ''
166}
167
168Thrift.Transport.prototype = {
169
170 //Gets the browser specific XmlHttpRequest Object
171 getXmlHttpRequestObject : function() {
172
173 try { return new XMLHttpRequest() } catch(e) {}
174 try { return new ActiveXObject("Msxml2.XMLHTTP") } catch (e) {}
175 try { return new ActiveXObject("Microsoft.XMLHTTP") } catch (e) {}
176
177 throw "Your browser doesn't support the XmlHttpRequest object. Try upgrading to Firefox."
178
179 },
180
181 flush : function(){
182
183 //async mode
184 if(this.url == undefined || this.url == '')
185 return this.send_buf;
186
187 var xreq = this.getXmlHttpRequestObject()
188
189 if (xreq.overrideMimeType)
190 xreq.overrideMimeType("application/json")
191
192 xreq.open("POST", this.url, false)
193 xreq.send(this.send_buf)
194
195 if (xreq.readyState != 4)
196 throw "encountered an unknown ajax ready state: "+xreq.readyState
197
198 if (xreq.status != 200)
199 throw "encountered a unknown request status: "+xreq.status
200
201 this.recv_buf = xreq.responseText
202 this.recv_buf_sz = this.recv_buf.length
203 this.wpos = this.recv_buf.length
204 this.rpos = 0
205 },
206
207 setRecvBuffer : function(buf){
208 this.recv_buf = buf
209 this.recv_buf_sz = this.recv_buf.length
210 this.wpos = this.recv_buf.length
211 this.rpos = 0
212 },
213
214 isOpen : function() {
215 return true
216 },
217
218 open : function() {},
219
220 close: function() {},
221
222 read : function(len) {
223 var avail = this.wpos - this.rpos
224
225 if(avail == 0)
226 return ''
227
228 var give = len
229
230 if(avail < len)
231 give = avail
232
233 var ret = this.read_buf.substr(this.rpos,give)
234 this.rpos += give
235
236 //clear buf when complete?
237 return ret
238 },
239
240 readAll : function() {
241 return this.recv_buf
242 },
243
244 write : function(buf){
245 this.send_buf = buf
246 },
247
248 getSendBuffer : function(){
249 return this.send_buf
250 }
251
252}
253
254
255
256Thrift.Protocol = function(transport){
257 this.transport = transport
258}
259
260Thrift.Protocol.Type = {}
261Thrift.Protocol.Type[ Thrift.Type.BOOL ] = '"tf"'
262Thrift.Protocol.Type[ Thrift.Type.BYTE ] = '"i8"'
263Thrift.Protocol.Type[ Thrift.Type.I16 ] = '"i16"'
264Thrift.Protocol.Type[ Thrift.Type.I32 ] = '"i32"'
265Thrift.Protocol.Type[ Thrift.Type.I64 ] = '"i64"'
266Thrift.Protocol.Type[ Thrift.Type.DOUBLE ] = '"dbl"'
267Thrift.Protocol.Type[ Thrift.Type.STRUCT ] = '"rec"'
268Thrift.Protocol.Type[ Thrift.Type.STRING ] = '"str"'
269Thrift.Protocol.Type[ Thrift.Type.MAP ] = '"map"'
270Thrift.Protocol.Type[ Thrift.Type.LIST ] = '"lst"'
271Thrift.Protocol.Type[ Thrift.Type.SET ] = '"set"'
272
273
274Thrift.Protocol.RType = {}
275Thrift.Protocol.RType[ "tf" ] = Thrift.Type.BOOL
276Thrift.Protocol.RType[ "i8" ] = Thrift.Type.BYTE
277Thrift.Protocol.RType[ "i16"] = Thrift.Type.I16
278Thrift.Protocol.RType[ "i32"] = Thrift.Type.I32
279Thrift.Protocol.RType[ "i64"] = Thrift.Type.I64
280Thrift.Protocol.RType[ "dbl"] = Thrift.Type.DOUBLE
281Thrift.Protocol.RType[ "rec"] = Thrift.Type.STRUCT
282Thrift.Protocol.RType[ "str"] = Thrift.Type.STRING
283Thrift.Protocol.RType[ "map"] = Thrift.Type.MAP
284Thrift.Protocol.RType[ "lst"] = Thrift.Type.LIST
285Thrift.Protocol.RType[ "set"] = Thrift.Type.SET
286
287Thrift.Protocol.Version = 1
288
289Thrift.Protocol.prototype = {
290
291 getTransport : function(){
292 return this.transport
293 },
294
295 //Write functions
296 writeMessageBegin : function(name,messageType,seqid){
297 this.tstack = new Array()
298 this.tpos = new Array();
299
300 this.tstack.push([Thrift.Protocol.Version,'"'+name+'"',messageType,seqid]);
301 },
302
303 writeMessageEnd : function(){
304 var obj = this.tstack.pop()
305
306 this.wobj = this.tstack.pop()
307 this.wobj.push(obj)
308
309 this.wbuf = "["+this.wobj.join(",")+"]";
310
311 this.transport.write(this.wbuf);
312 },
313
314
315 writeStructBegin : function(name){
316 this.tpos.push(this.tstack.length)
317 this.tstack.push({})
318 },
319
320 writeStructEnd : function(){
321
322 var p = this.tpos.pop()
323 var struct = this.tstack[p]
324 var str = "{"
325 var first = true
326 for( var key in struct ){
327 if(first)
328 first = false;
329 else
330 str += ",";
331
332 str += key+":"+struct[key]
333 }
334
335 str += "}"
336 this.tstack[p] = str;
337 },
338
339 writeFieldBegin : function(name,fieldType,fieldId){
340 this.tpos.push(this.tstack.length)
341 this.tstack.push({"fieldId" : '"'+fieldId+'"', "fieldType" : Thrift.Protocol.Type[fieldType]});
342
343 },
344
345 writeFieldEnd : function(){
346 var value = this.tstack.pop()
347 var fieldInfo = this.tstack.pop()
348
349 this.tstack[this.tstack.length-1][fieldInfo.fieldId] = "{"+fieldInfo.fieldType+":"+value+"}"
350 this.tpos.pop()
351 },
352
353 writeFieldStop : function(){
354 //na
355 },
356
357 writeMapBegin : function(keyType,valType,size){
358 //size is invalid, we'll set it on end.
359 this.tpos.push(this.tstack.length)
360 this.tstack.push([Thrift.Protocol.Type[keyType],Thrift.Protocol.Type[valType],0])
361 },
362
363 writeMapEnd : function(){
364 var p = this.tpos.pop()
365
366 if(p == this.tstack.length)
367 return;
368
369 if((this.tstack.length - p - 1) % 2 != 0)
370 this.tstack.push("");
371
372 var size = (this.tstack.length - p - 1)/2
373
374 this.tstack[p][this.tstack[p].length-1] = size;
375
376 var map = "{"
377 var first = true
378 while( this.tstack.length > p+1 ){
379 var v = this.tstack.pop()
380 var k = this.tstack.pop()
381 if(first){
382 first = false
383 }else{
384 map += ","
385 }
386
387 map += '"'+k+'":'+v
388 }
389 map += "}"
390
391 this.tstack[p].push(map)
392 this.tstack[p] = "["+this.tstack[p].join(",")+"]"
393 },
394
395 writeListBegin : function(elemType,size){
396 this.tpos.push(this.tstack.length)
397 this.tstack.push([Thrift.Protocol.Type[elemType],size]);
398 },
399
400 writeListEnd : function(){
401 var p = this.tpos.pop()
402
403 while( this.tstack.length > p+1 ){
T Jake Lucianiefabb892010-07-28 22:31:12 +0000404 var tmpVal = this.tstack[p+1]
405 this.tstack.splice(p+1, 1)
406 this.tstack[p].push(tmpVal)
T Jake Luciani322caa22010-02-15 03:24:55 +0000407 }
408
409 this.tstack[p] = '['+this.tstack[p].join(",")+']';
410 },
411
412 writeSetBegin : function(elemType,size){
413 this.tpos.push(this.tstack.length)
414 this.tstack.push([Thrift.Protocol.Type[elemType],size]);
415 },
416
417 writeSetEnd : function(){
418 var p = this.tpos.pop()
419
420 while( this.tstack.length > p+1 ){
T Jake Lucianiefabb892010-07-28 22:31:12 +0000421 var tmpVal = this.tstack[p+1]
422 this.tstack.splice(p+1, 1)
423 this.tstack[p].push(tmpVal)
T Jake Luciani322caa22010-02-15 03:24:55 +0000424 }
425
426 this.tstack[p] = '['+this.tstack[p].join(",")+']';
427 },
428
429 writeBool : function(value){
430 this.tstack.push( value ? 1 : 0 );
431 },
432
433 writeByte : function(i8){
434 this.tstack.push(i8);
435 },
436
437 writeI16 : function(i16){
438 this.tstack.push(i16);
439 },
440
441 writeI32 : function(i32){
442 this.tstack.push(i32);
443 },
444
445 writeI64 : function(i64){
446 this.tstack.push(i64);
447 },
448
449 writeDouble : function(dbl){
450 this.tstack.push(dbl);
451 },
452
453 writeString : function(str){
454 this.tstack.push('"'+encodeURIComponent(str)+'"');
455 },
456
457 writeBinary : function(str){
458 this.writeString(str);
459 },
460
461
462
463 // Reading functions
464 readMessageBegin : function(name, messageType, seqid){
465 this.rstack = new Array()
466 this.rpos = new Array()
467
468 this.robj = eval(this.transport.readAll())
469
470 var r = {}
471 var version = this.robj.shift()
472
473 if(version != Thrift.Protocol.Version){
474 throw "Wrong thrift protocol version: "+version
475 }
476
477 r["fname"] = this.robj.shift()
478 r["mtype"] = this.robj.shift()
479 r["rseqid"] = this.robj.shift()
480
481
482 //get to the main obj
483 this.rstack.push(this.robj.shift())
484
485 return r
486 },
487
488
489 readMessageEnd : function(){
490 },
491
492 readStructBegin : function(name){
T Jake Lucianiefabb892010-07-28 22:31:12 +0000493 var r = {}
494 r["fname"] = ''
495
496 //incase this is an array of structs
497 if(this.rstack[this.rstack.length-1] instanceof Array)
498 this.rstack.push(this.rstack[this.rstack.length-1].shift())
499
500 return r
T Jake Luciani322caa22010-02-15 03:24:55 +0000501 },
502
503 readStructEnd : function(){
T Jake Lucianiefabb892010-07-28 22:31:12 +0000504 if(this.rstack[this.rstack.length-2] instanceof Array)
505 this.rstack.pop()
T Jake Luciani322caa22010-02-15 03:24:55 +0000506 },
507
508 readFieldBegin : function(){
509 var r = {};
510
511 var fid = -1
512 var ftype = Thrift.Type.STOP
513
514 //get a fieldId
515 for(var f in (this.rstack[this.rstack.length-1])){
516 if(f == null) continue
517
518 fid = parseInt(f)
519 this.rpos.push(this.rstack.length)
520
521 var field = this.rstack[this.rstack.length-1][fid]
522
523 //remove so we don't see it again
524 delete this.rstack[this.rstack.length-1][fid]
525
526 this.rstack.push(field)
527
528 break
529 }
530
531 if(fid != -1){
532
533 //should only be 1 of these but this is the only
534 //way to match a key
535 for(var f in (this.rstack[this.rstack.length-1])){
536 if(Thrift.Protocol.RType[f] == null ) continue
537
538 ftype = Thrift.Protocol.RType[f]
539 this.rstack[this.rstack.length-1] = this.rstack[this.rstack.length-1][f]
540 }
541 }
542
543 r["fname"] = ''
544 r["ftype"] = ftype
545 r["fid"] = fid
546
547
548 return r
549 },
550
551 readFieldEnd : function(){
552 var pos = this.rpos.pop()
553
554 //get back to the right place in the stack
555 while(this.rstack.length > pos)
556 this.rstack.pop();
557
558 },
559
560 readMapBegin : function(keyType,valType,size){
561
T Jake Lucianib22b51e2010-08-06 02:37:45 +0000562 var map = this.rstack.pop()
T Jake Luciani322caa22010-02-15 03:24:55 +0000563
564 var r = {};
565 r["ktype"] = Thrift.Protocol.RType[map.shift()]
566 r["vtype"] = Thrift.Protocol.RType[map.shift()]
567 r["size"] = map.shift()
568
569
570 this.rpos.push(this.rstack.length)
571 this.rstack.push(map.shift())
572
573 return r;
574 },
575
576 readMapEnd : function(){
577 this.readFieldEnd()
578 },
579
580 readListBegin : function(elemType,size){
581
582 var list = this.rstack[this.rstack.length-1]
583
584 var r = {};
585 r["etype"] = Thrift.Protocol.RType[list.shift()];
586 r["size" ] = list.shift();
587
588
589 this.rpos.push(this.rstack.length);
T Jake Luciani127909c2010-07-10 14:58:51 +0000590 this.rstack.push(list)
T Jake Lucianiefabb892010-07-28 22:31:12 +0000591
T Jake Luciani322caa22010-02-15 03:24:55 +0000592 return r;
593 },
594
595 readListEnd : function(){
596 this.readFieldEnd()
597 },
598
599 readSetBegin : function(elemType,size){
600 return this.readListBegin(elemType,size)
601 },
602
603 readSetEnd : function(){
604 return this.readListEnd()
605 },
606
607 readBool : function(){
608 var r = this.readI32()
609
610 if( r != null && r["value"] == "1" ){
611 r["value"] = true
612 }else{
613 r["value"] = false
614 }
615
616 return r
617 },
618
619 readByte : function(){
620 return this.readI32()
621 },
622
623 readI16 : function(){
624 return this.readI32()
625 },
626
627
T Jake Lucianiefabb892010-07-28 22:31:12 +0000628 readI32 : function(f){
629 if(f == undefined)
630 f = this.rstack[this.rstack.length-1]
631
T Jake Luciani322caa22010-02-15 03:24:55 +0000632 var r = {}
633
634 if(f instanceof Array){
T Jake Lucianiefabb892010-07-28 22:31:12 +0000635 if(f.length == 0)
636 r["value"] = undefined
637 else
638 r["value"] = f.shift()
639
T Jake Luciani322caa22010-02-15 03:24:55 +0000640 }else if(f instanceof Object){
641 for(var i in f){
642 if(i == null) continue
643 this.rstack.push(f[i])
644 delete f[i]
T Jake Lucianiefabb892010-07-28 22:31:12 +0000645
T Jake Luciani322caa22010-02-15 03:24:55 +0000646 r["value"] = i
647 break
648 }
649 } else {
650 r["value"] = f
651 }
652
T Jake Luciani322caa22010-02-15 03:24:55 +0000653 return r
654 },
655
656 readI64 : function(){
657 return this.readI32()
658 },
659
660 readDouble : function(){
661 return this.readI32()
662 },
663
664 readString : function(){
665 var r = this.readI32()
666 r["value"] = decodeURIComponent(r["value"])
667
668 return r
669 },
670
671 readBinary : function(){
672 return this.readString()
673 },
674
675
676 //Method to arbitrarily skip over data.
677 skip : function(type){
678 throw "skip not supported yet"
679 }
680
681}
682
683
684