blob: b70986f6adaab79fececcb1020141353050029ba [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
57Thrift.TApplicationException = {
58 "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 ){
404 this.tstack[p].push(this.tstack.pop())
405 }
406
407 this.tstack[p] = '['+this.tstack[p].join(",")+']';
408 },
409
410 writeSetBegin : function(elemType,size){
411 this.tpos.push(this.tstack.length)
412 this.tstack.push([Thrift.Protocol.Type[elemType],size]);
413 },
414
415 writeSetEnd : function(){
416 var p = this.tpos.pop()
417
418 while( this.tstack.length > p+1 ){
419 this.tstack[p].push(this.tstack.pop())
420 }
421
422 this.tstack[p] = '['+this.tstack[p].join(",")+']';
423 },
424
425 writeBool : function(value){
426 this.tstack.push( value ? 1 : 0 );
427 },
428
429 writeByte : function(i8){
430 this.tstack.push(i8);
431 },
432
433 writeI16 : function(i16){
434 this.tstack.push(i16);
435 },
436
437 writeI32 : function(i32){
438 this.tstack.push(i32);
439 },
440
441 writeI64 : function(i64){
442 this.tstack.push(i64);
443 },
444
445 writeDouble : function(dbl){
446 this.tstack.push(dbl);
447 },
448
449 writeString : function(str){
450 this.tstack.push('"'+encodeURIComponent(str)+'"');
451 },
452
453 writeBinary : function(str){
454 this.writeString(str);
455 },
456
457
458
459 // Reading functions
460 readMessageBegin : function(name, messageType, seqid){
461 this.rstack = new Array()
462 this.rpos = new Array()
463
464 this.robj = eval(this.transport.readAll())
465
466 var r = {}
467 var version = this.robj.shift()
468
469 if(version != Thrift.Protocol.Version){
470 throw "Wrong thrift protocol version: "+version
471 }
472
473 r["fname"] = this.robj.shift()
474 r["mtype"] = this.robj.shift()
475 r["rseqid"] = this.robj.shift()
476
477
478 //get to the main obj
479 this.rstack.push(this.robj.shift())
480
481 return r
482 },
483
484
485 readMessageEnd : function(){
486 },
487
488 readStructBegin : function(name){
489 var r = {};
490 r["fname"] = '';
491
492 return r;
493 },
494
495 readStructEnd : function(){
496 },
497
498 readFieldBegin : function(){
499 var r = {};
500
501 var fid = -1
502 var ftype = Thrift.Type.STOP
503
504 //get a fieldId
505 for(var f in (this.rstack[this.rstack.length-1])){
506 if(f == null) continue
507
508 fid = parseInt(f)
509 this.rpos.push(this.rstack.length)
510
511 var field = this.rstack[this.rstack.length-1][fid]
512
513 //remove so we don't see it again
514 delete this.rstack[this.rstack.length-1][fid]
515
516 this.rstack.push(field)
517
518 break
519 }
520
521 if(fid != -1){
522
523 //should only be 1 of these but this is the only
524 //way to match a key
525 for(var f in (this.rstack[this.rstack.length-1])){
526 if(Thrift.Protocol.RType[f] == null ) continue
527
528 ftype = Thrift.Protocol.RType[f]
529 this.rstack[this.rstack.length-1] = this.rstack[this.rstack.length-1][f]
530 }
531 }
532
533 r["fname"] = ''
534 r["ftype"] = ftype
535 r["fid"] = fid
536
537
538 return r
539 },
540
541 readFieldEnd : function(){
542 var pos = this.rpos.pop()
543
544 //get back to the right place in the stack
545 while(this.rstack.length > pos)
546 this.rstack.pop();
547
548 },
549
550 readMapBegin : function(keyType,valType,size){
551
552 var map = this.rstack[this.rstack.length-1]
553
554 var r = {};
555 r["ktype"] = Thrift.Protocol.RType[map.shift()]
556 r["vtype"] = Thrift.Protocol.RType[map.shift()]
557 r["size"] = map.shift()
558
559
560 this.rpos.push(this.rstack.length)
561 this.rstack.push(map.shift())
562
563 return r;
564 },
565
566 readMapEnd : function(){
567 this.readFieldEnd()
568 },
569
570 readListBegin : function(elemType,size){
571
572 var list = this.rstack[this.rstack.length-1]
573
574 var r = {};
575 r["etype"] = Thrift.Protocol.RType[list.shift()];
576 r["size" ] = list.shift();
577
578
579 this.rpos.push(this.rstack.length);
580 this.rstack.push(list.shift())
581
582
583 return r;
584 },
585
586 readListEnd : function(){
587 this.readFieldEnd()
588 },
589
590 readSetBegin : function(elemType,size){
591 return this.readListBegin(elemType,size)
592 },
593
594 readSetEnd : function(){
595 return this.readListEnd()
596 },
597
598 readBool : function(){
599 var r = this.readI32()
600
601 if( r != null && r["value"] == "1" ){
602 r["value"] = true
603 }else{
604 r["value"] = false
605 }
606
607 return r
608 },
609
610 readByte : function(){
611 return this.readI32()
612 },
613
614 readI16 : function(){
615 return this.readI32()
616 },
617
618
619 readI32 : function(){
620 var f = this.rstack[this.rstack.length-1]
621 var r = {}
622
623 if(f instanceof Array){
624 r["value"] = f.pop()
625
626 }else if(f instanceof Object){
627 for(var i in f){
628 if(i == null) continue
629 this.rstack.push(f[i])
630 delete f[i]
631
632 r["value"] = i
633 break
634 }
635 } else {
636 r["value"] = f
637 }
638
639
640 return r
641 },
642
643 readI64 : function(){
644 return this.readI32()
645 },
646
647 readDouble : function(){
648 return this.readI32()
649 },
650
651 readString : function(){
652 var r = this.readI32()
653 r["value"] = decodeURIComponent(r["value"])
654
655 return r
656 },
657
658 readBinary : function(){
659 return this.readString()
660 },
661
662
663 //Method to arbitrarily skip over data.
664 skip : function(type){
665 throw "skip not supported yet"
666 }
667
668}
669
670
671