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