blob: 4d66861d9c4a5f48cb40cff7f2a28f38799a5e25 [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
Roger Meier55ea68f2011-02-16 19:29:50 +000045 },
46
47 objectLength : function(obj) {
48 var length = 0
49 for (k in obj)
50 if (obj.hasOwnProperty(k))
51 length++
52 return length
53 },
54
55 inherits : function(constructor, superConstructor) {
56 function F(){} //Prototypal Inheritance http://javascript.crockford.com/prototypal.html
57 F.prototype = superConstructor.prototype
58 constructor.prototype = new F()
T Jake Luciani322caa22010-02-15 03:24:55 +000059 }
60}
61
Roger Meier55ea68f2011-02-16 19:29:50 +000062
T Jake Luciani322caa22010-02-15 03:24:55 +000063Thrift.TException = {}
64Thrift.TException.prototype = {
65 initialize: function( message, code ) {
66 this.message = message;
67 this.code = (code == null) ? 0 : code;
68 }
69}
70
71
T Jake Lucianiefabb892010-07-28 22:31:12 +000072Thrift.TApplicationExceptionType = {
T Jake Luciani322caa22010-02-15 03:24:55 +000073 "UNKNOWN" : 0,
74 "UNKNOWN_METHOD" : 1,
75 "INVALID_MESSAGE_TYPE" : 2,
76 "WRONG_METHOD_NAME" : 3,
77 "BAD_SEQUENCE_ID" : 4,
78 "MISSING_RESULT" : 5
79}
80
81Thrift.TApplicationException = function(message, code){
82 this.message = message
83 this.code = (code == null) ? 0 : code
84}
85
86Thrift.TApplicationException.prototype = {
87
88 read : function(input){
T Jake Luciani322caa22010-02-15 03:24:55 +000089 while(1){
T Jake Luciani322caa22010-02-15 03:24:55 +000090 ret = input.readFieldBegin()
91
Roger Meier76d55f62011-02-22 20:56:45 +000092 if(ret.ftype == Thrift.Type.STOP)
T Jake Luciani322caa22010-02-15 03:24:55 +000093 break
94
95 var fid = ret.fid
96
97 switch(fid){
98 case 1:
Roger Meier76d55f62011-02-22 20:56:45 +000099 if( ret.ftype == Thrift.Type.STRING ){
T Jake Luciani322caa22010-02-15 03:24:55 +0000100 ret = input.readString()
101 this.message = ret.value
102 } else {
103 ret = input.skip(ret.ftype)
104 }
105
106 break
107 case 2:
Roger Meier76d55f62011-02-22 20:56:45 +0000108 if( ret.ftype == Thrift.Type.I32 ){
T Jake Luciani322caa22010-02-15 03:24:55 +0000109 ret = input.readI32()
110 this.code = ret.value
111 } else {
112 ret = input.skip(ret.ftype)
113 }
114 break
115
116 default:
117 ret = input.skip(ret.ftype)
118 break
119 }
120
121 input.readFieldEnd()
T Jake Luciani322caa22010-02-15 03:24:55 +0000122 }
123
124 input.readStructEnd()
T Jake Luciani322caa22010-02-15 03:24:55 +0000125 },
126
127 write: function(output){
128 var xfer = 0;
129
130 output.writeStructBegin('TApplicationException');
131
132 if (this.message) {
Roger Meier76d55f62011-02-22 20:56:45 +0000133 output.writeFieldBegin('message', Thrift.Type.STRING, 1)
T Jake Luciani322caa22010-02-15 03:24:55 +0000134 output.writeString(this.getMessage())
135 output.writeFieldEnd()
136 }
137
138 if (this.code) {
Roger Meier76d55f62011-02-22 20:56:45 +0000139 output.writeFieldBegin('type', Thrift.Type.I32, 2)
T Jake Luciani322caa22010-02-15 03:24:55 +0000140 output.writeI32(this.code)
141 output.writeFieldEnd()
142 }
143
144 output.writeFieldStop()
145 output.writeStructEnd()
T Jake Luciani322caa22010-02-15 03:24:55 +0000146 },
147
148 getCode : function() {
149 return this.code
150 },
151
152 getMessage : function() {
153 return this.message
154 }
155}
156
157
158
159/**
160 *If you do not specify a url then you must handle ajax on your own.
161 *This is how to use js bindings in a async fashion.
162 */
163Thrift.Transport = function(url){
164 this.url = url
165 this.wpos = 0
166 this.rpos = 0
167
168 this.send_buf = ''
169 this.recv_buf = ''
170}
171
172Thrift.Transport.prototype = {
173
174 //Gets the browser specific XmlHttpRequest Object
175 getXmlHttpRequestObject : function() {
T Jake Luciani416eea92010-09-17 23:38:25 +0000176
T Jake Luciani322caa22010-02-15 03:24:55 +0000177 try { return new XMLHttpRequest() } catch(e) {}
178 try { return new ActiveXObject("Msxml2.XMLHTTP") } catch (e) {}
179 try { return new ActiveXObject("Microsoft.XMLHTTP") } catch (e) {}
180
181 throw "Your browser doesn't support the XmlHttpRequest object. Try upgrading to Firefox."
T Jake Luciani416eea92010-09-17 23:38:25 +0000182
T Jake Luciani322caa22010-02-15 03:24:55 +0000183 },
184
185 flush : function(){
186
187 //async mode
188 if(this.url == undefined || this.url == '')
189 return this.send_buf;
190
191 var xreq = this.getXmlHttpRequestObject()
T Jake Luciani416eea92010-09-17 23:38:25 +0000192
T Jake Luciani322caa22010-02-15 03:24:55 +0000193 if (xreq.overrideMimeType)
194 xreq.overrideMimeType("application/json")
195
196 xreq.open("POST", this.url, false)
197 xreq.send(this.send_buf)
198
199 if (xreq.readyState != 4)
200 throw "encountered an unknown ajax ready state: "+xreq.readyState
201
202 if (xreq.status != 200)
203 throw "encountered a unknown request status: "+xreq.status
204
205 this.recv_buf = xreq.responseText
206 this.recv_buf_sz = this.recv_buf.length
207 this.wpos = this.recv_buf.length
208 this.rpos = 0
209 },
210
211 setRecvBuffer : function(buf){
212 this.recv_buf = buf
213 this.recv_buf_sz = this.recv_buf.length
214 this.wpos = this.recv_buf.length
215 this.rpos = 0
216 },
217
218 isOpen : function() {
219 return true
220 },
221
222 open : function() {},
223
224 close: function() {},
225
226 read : function(len) {
227 var avail = this.wpos - this.rpos
228
229 if(avail == 0)
230 return ''
231
232 var give = len
233
234 if(avail < len)
235 give = avail
236
237 var ret = this.read_buf.substr(this.rpos,give)
238 this.rpos += give
239
240 //clear buf when complete?
241 return ret
242 },
243
244 readAll : function() {
245 return this.recv_buf
246 },
247
248 write : function(buf){
249 this.send_buf = buf
250 },
251
252 getSendBuffer : function(){
253 return this.send_buf
254 }
255
256}
257
258
259
260Thrift.Protocol = function(transport){
261 this.transport = transport
262}
263
264Thrift.Protocol.Type = {}
265Thrift.Protocol.Type[ Thrift.Type.BOOL ] = '"tf"'
266Thrift.Protocol.Type[ Thrift.Type.BYTE ] = '"i8"'
267Thrift.Protocol.Type[ Thrift.Type.I16 ] = '"i16"'
268Thrift.Protocol.Type[ Thrift.Type.I32 ] = '"i32"'
269Thrift.Protocol.Type[ Thrift.Type.I64 ] = '"i64"'
270Thrift.Protocol.Type[ Thrift.Type.DOUBLE ] = '"dbl"'
271Thrift.Protocol.Type[ Thrift.Type.STRUCT ] = '"rec"'
272Thrift.Protocol.Type[ Thrift.Type.STRING ] = '"str"'
273Thrift.Protocol.Type[ Thrift.Type.MAP ] = '"map"'
274Thrift.Protocol.Type[ Thrift.Type.LIST ] = '"lst"'
275Thrift.Protocol.Type[ Thrift.Type.SET ] = '"set"'
276
277
278Thrift.Protocol.RType = {}
279Thrift.Protocol.RType[ "tf" ] = Thrift.Type.BOOL
280Thrift.Protocol.RType[ "i8" ] = Thrift.Type.BYTE
281Thrift.Protocol.RType[ "i16"] = Thrift.Type.I16
282Thrift.Protocol.RType[ "i32"] = Thrift.Type.I32
283Thrift.Protocol.RType[ "i64"] = Thrift.Type.I64
284Thrift.Protocol.RType[ "dbl"] = Thrift.Type.DOUBLE
285Thrift.Protocol.RType[ "rec"] = Thrift.Type.STRUCT
286Thrift.Protocol.RType[ "str"] = Thrift.Type.STRING
287Thrift.Protocol.RType[ "map"] = Thrift.Type.MAP
288Thrift.Protocol.RType[ "lst"] = Thrift.Type.LIST
289Thrift.Protocol.RType[ "set"] = Thrift.Type.SET
290
291Thrift.Protocol.Version = 1
292
293Thrift.Protocol.prototype = {
294
295 getTransport : function(){
296 return this.transport
297 },
298
299 //Write functions
300 writeMessageBegin : function(name,messageType,seqid){
301 this.tstack = new Array()
302 this.tpos = new Array();
303
304 this.tstack.push([Thrift.Protocol.Version,'"'+name+'"',messageType,seqid]);
305 },
306
307 writeMessageEnd : function(){
308 var obj = this.tstack.pop()
309
310 this.wobj = this.tstack.pop()
311 this.wobj.push(obj)
312
313 this.wbuf = "["+this.wobj.join(",")+"]";
314
315 this.transport.write(this.wbuf);
316 },
317
318
319 writeStructBegin : function(name){
320 this.tpos.push(this.tstack.length)
321 this.tstack.push({})
322 },
323
324 writeStructEnd : function(){
325
326 var p = this.tpos.pop()
327 var struct = this.tstack[p]
328 var str = "{"
329 var first = true
330 for( var key in struct ){
331 if(first)
332 first = false;
333 else
334 str += ",";
335
336 str += key+":"+struct[key]
337 }
338
339 str += "}"
340 this.tstack[p] = str;
341 },
342
343 writeFieldBegin : function(name,fieldType,fieldId){
344 this.tpos.push(this.tstack.length)
345 this.tstack.push({"fieldId" : '"'+fieldId+'"', "fieldType" : Thrift.Protocol.Type[fieldType]});
346
347 },
348
349 writeFieldEnd : function(){
350 var value = this.tstack.pop()
351 var fieldInfo = this.tstack.pop()
352
353 this.tstack[this.tstack.length-1][fieldInfo.fieldId] = "{"+fieldInfo.fieldType+":"+value+"}"
354 this.tpos.pop()
355 },
356
357 writeFieldStop : function(){
358 //na
359 },
360
361 writeMapBegin : function(keyType,valType,size){
362 //size is invalid, we'll set it on end.
363 this.tpos.push(this.tstack.length)
364 this.tstack.push([Thrift.Protocol.Type[keyType],Thrift.Protocol.Type[valType],0])
365 },
366
367 writeMapEnd : function(){
368 var p = this.tpos.pop()
369
370 if(p == this.tstack.length)
371 return;
372
373 if((this.tstack.length - p - 1) % 2 != 0)
374 this.tstack.push("");
375
376 var size = (this.tstack.length - p - 1)/2
377
378 this.tstack[p][this.tstack[p].length-1] = size;
379
Roger Meierd9924982011-02-24 16:04:03 +0000380 var map = "}"
T Jake Luciani322caa22010-02-15 03:24:55 +0000381 var first = true
382 while( this.tstack.length > p+1 ){
383 var v = this.tstack.pop()
384 var k = this.tstack.pop()
385 if(first){
386 first = false
387 }else{
Roger Meierd9924982011-02-24 16:04:03 +0000388 map = "," + map
T Jake Luciani322caa22010-02-15 03:24:55 +0000389 }
390
Roger Meierd9924982011-02-24 16:04:03 +0000391 map = '"'+k+'":'+v + map
T Jake Luciani322caa22010-02-15 03:24:55 +0000392 }
Roger Meierd9924982011-02-24 16:04:03 +0000393 map = "{" + map
T Jake Luciani322caa22010-02-15 03:24:55 +0000394
395 this.tstack[p].push(map)
396 this.tstack[p] = "["+this.tstack[p].join(",")+"]"
397 },
398
399 writeListBegin : function(elemType,size){
400 this.tpos.push(this.tstack.length)
401 this.tstack.push([Thrift.Protocol.Type[elemType],size]);
402 },
403
404 writeListEnd : function(){
405 var p = this.tpos.pop()
406
407 while( this.tstack.length > p+1 ){
T Jake Lucianiefabb892010-07-28 22:31:12 +0000408 var tmpVal = this.tstack[p+1]
409 this.tstack.splice(p+1, 1)
410 this.tstack[p].push(tmpVal)
T Jake Luciani322caa22010-02-15 03:24:55 +0000411 }
412
413 this.tstack[p] = '['+this.tstack[p].join(",")+']';
414 },
415
416 writeSetBegin : function(elemType,size){
417 this.tpos.push(this.tstack.length)
418 this.tstack.push([Thrift.Protocol.Type[elemType],size]);
419 },
420
421 writeSetEnd : function(){
422 var p = this.tpos.pop()
423
424 while( this.tstack.length > p+1 ){
T Jake Lucianiefabb892010-07-28 22:31:12 +0000425 var tmpVal = this.tstack[p+1]
426 this.tstack.splice(p+1, 1)
427 this.tstack[p].push(tmpVal)
T Jake Luciani322caa22010-02-15 03:24:55 +0000428 }
429
430 this.tstack[p] = '['+this.tstack[p].join(",")+']';
431 },
432
433 writeBool : function(value){
434 this.tstack.push( value ? 1 : 0 );
435 },
436
437 writeByte : function(i8){
438 this.tstack.push(i8);
439 },
440
441 writeI16 : function(i16){
442 this.tstack.push(i16);
443 },
444
445 writeI32 : function(i32){
446 this.tstack.push(i32);
447 },
448
449 writeI64 : function(i64){
450 this.tstack.push(i64);
451 },
452
453 writeDouble : function(dbl){
454 this.tstack.push(dbl);
455 },
456
457 writeString : function(str){
T Jake Luciani416eea92010-09-17 23:38:25 +0000458 // We do not encode uri components for wire transfer:
459 if(str === null) {
460 this.tstack.push(null);
461 } else {
462 // concat may be slower than building a byte buffer
463 var escapedString = "";
464 for(var i = 0; i < str.length; i++) {
465 var ch = str.charAt(i); // a single double quote: "
466 if(ch === '\"') {
467 escapedString += '\\\"'; // write out as: \"
468 } else if(ch === '\\') { // a single backslash: \
469 escapedString += '\\\\'; // write out as: \\
470 /* Currently escaped forward slashes break TJSONProtocol.
471 * As it stands, we can simply pass forward slashes into our strings
472 * across the wire without being escaped.
473 * I think this is the protocol's bug, not thrift.js
474 * } else if(ch === '/') { // a single forward slash: /
475 * escapedString += '\\/'; // write out as \/
476 * }
477 */
478 } else if(ch === '\b') { // a single backspace: invisible
479 escapedString += '\\b'; // write out as: \b"
480 } else if(ch === '\f') { // a single formfeed: invisible
481 escapedString += '\\f'; // write out as: \f"
482 } else if(ch === '\n') { // a single newline: invisible
483 escapedString += '\\n'; // write out as: \n"
484 } else if(ch === '\r') { // a single return: invisible
485 escapedString += '\\r'; // write out as: \r"
486 } else if(ch === '\t') { // a single tab: invisible
487 escapedString += '\\t'; // write out as: \t"
488 } else {
489 escapedString += ch; // Else it need not be escaped
490 }
491 }
492 this.tstack.push('"' + escapedString + '"');
493 }
T Jake Luciani322caa22010-02-15 03:24:55 +0000494 },
495
496 writeBinary : function(str){
497 this.writeString(str);
498 },
499
500
501
502 // Reading functions
503 readMessageBegin : function(name, messageType, seqid){
504 this.rstack = new Array()
505 this.rpos = new Array()
506
507 this.robj = eval(this.transport.readAll())
508
509 var r = {}
510 var version = this.robj.shift()
511
512 if(version != Thrift.Protocol.Version){
513 throw "Wrong thrift protocol version: "+version
514 }
515
516 r["fname"] = this.robj.shift()
517 r["mtype"] = this.robj.shift()
518 r["rseqid"] = this.robj.shift()
519
520
521 //get to the main obj
522 this.rstack.push(this.robj.shift())
523
524 return r
525 },
526
527
528 readMessageEnd : function(){
529 },
530
531 readStructBegin : function(name){
T Jake Lucianiefabb892010-07-28 22:31:12 +0000532 var r = {}
533 r["fname"] = ''
534
535 //incase this is an array of structs
536 if(this.rstack[this.rstack.length-1] instanceof Array)
537 this.rstack.push(this.rstack[this.rstack.length-1].shift())
538
539 return r
T Jake Luciani322caa22010-02-15 03:24:55 +0000540 },
541
542 readStructEnd : function(){
T Jake Lucianiefabb892010-07-28 22:31:12 +0000543 if(this.rstack[this.rstack.length-2] instanceof Array)
544 this.rstack.pop()
T Jake Luciani322caa22010-02-15 03:24:55 +0000545 },
546
547 readFieldBegin : function(){
548 var r = {};
549
550 var fid = -1
551 var ftype = Thrift.Type.STOP
552
553 //get a fieldId
554 for(var f in (this.rstack[this.rstack.length-1])){
555 if(f == null) continue
556
557 fid = parseInt(f)
558 this.rpos.push(this.rstack.length)
559
560 var field = this.rstack[this.rstack.length-1][fid]
561
562 //remove so we don't see it again
563 delete this.rstack[this.rstack.length-1][fid]
564
565 this.rstack.push(field)
566
567 break
568 }
569
570 if(fid != -1){
571
572 //should only be 1 of these but this is the only
573 //way to match a key
574 for(var f in (this.rstack[this.rstack.length-1])){
575 if(Thrift.Protocol.RType[f] == null ) continue
576
577 ftype = Thrift.Protocol.RType[f]
578 this.rstack[this.rstack.length-1] = this.rstack[this.rstack.length-1][f]
579 }
580 }
581
582 r["fname"] = ''
583 r["ftype"] = ftype
584 r["fid"] = fid
585
586
587 return r
588 },
589
590 readFieldEnd : function(){
591 var pos = this.rpos.pop()
592
593 //get back to the right place in the stack
594 while(this.rstack.length > pos)
595 this.rstack.pop();
596
597 },
598
599 readMapBegin : function(keyType,valType,size){
600
T Jake Lucianib22b51e2010-08-06 02:37:45 +0000601 var map = this.rstack.pop()
T Jake Luciani322caa22010-02-15 03:24:55 +0000602
603 var r = {};
604 r["ktype"] = Thrift.Protocol.RType[map.shift()]
605 r["vtype"] = Thrift.Protocol.RType[map.shift()]
606 r["size"] = map.shift()
607
608
609 this.rpos.push(this.rstack.length)
610 this.rstack.push(map.shift())
611
612 return r;
613 },
614
615 readMapEnd : function(){
616 this.readFieldEnd()
617 },
618
619 readListBegin : function(elemType,size){
620
621 var list = this.rstack[this.rstack.length-1]
622
623 var r = {};
624 r["etype"] = Thrift.Protocol.RType[list.shift()];
625 r["size" ] = list.shift();
626
627
628 this.rpos.push(this.rstack.length);
T Jake Luciani127909c2010-07-10 14:58:51 +0000629 this.rstack.push(list)
T Jake Lucianiefabb892010-07-28 22:31:12 +0000630
T Jake Luciani322caa22010-02-15 03:24:55 +0000631 return r;
632 },
633
634 readListEnd : function(){
635 this.readFieldEnd()
636 },
637
638 readSetBegin : function(elemType,size){
639 return this.readListBegin(elemType,size)
640 },
641
642 readSetEnd : function(){
643 return this.readListEnd()
644 },
645
646 readBool : function(){
647 var r = this.readI32()
648
649 if( r != null && r["value"] == "1" ){
650 r["value"] = true
651 }else{
652 r["value"] = false
653 }
654
655 return r
656 },
657
658 readByte : function(){
659 return this.readI32()
660 },
661
662 readI16 : function(){
663 return this.readI32()
664 },
665
666
T Jake Lucianiefabb892010-07-28 22:31:12 +0000667 readI32 : function(f){
668 if(f == undefined)
669 f = this.rstack[this.rstack.length-1]
670
T Jake Luciani322caa22010-02-15 03:24:55 +0000671 var r = {}
672
673 if(f instanceof Array){
T Jake Lucianiefabb892010-07-28 22:31:12 +0000674 if(f.length == 0)
675 r["value"] = undefined
676 else
677 r["value"] = f.shift()
678
T Jake Luciani322caa22010-02-15 03:24:55 +0000679 }else if(f instanceof Object){
680 for(var i in f){
681 if(i == null) continue
682 this.rstack.push(f[i])
683 delete f[i]
T Jake Lucianiefabb892010-07-28 22:31:12 +0000684
T Jake Luciani322caa22010-02-15 03:24:55 +0000685 r["value"] = i
686 break
687 }
688 } else {
689 r["value"] = f
Roger Meierd9924982011-02-24 16:04:03 +0000690 this.rstack.pop()
T Jake Luciani322caa22010-02-15 03:24:55 +0000691 }
692
T Jake Luciani322caa22010-02-15 03:24:55 +0000693 return r
694 },
695
696 readI64 : function(){
697 return this.readI32()
698 },
699
700 readDouble : function(){
701 return this.readI32()
702 },
703
704 readString : function(){
705 var r = this.readI32()
T Jake Luciani322caa22010-02-15 03:24:55 +0000706 return r
707 },
708
709 readBinary : function(){
710 return this.readString()
711 },
712
713
714 //Method to arbitrarily skip over data.
715 skip : function(type){
716 throw "skip not supported yet"
717 }
718
719}