1  /*
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  */
19 
20 package org.apache.thrift.protocol;
21 
22 import java.io.UnsupportedEncodingException;
23 
24 import org.apache.thrift.TException;
25 import org.apache.thrift.transport.TTransport;
26 
27 /**
28  * Binary protocol implementation for thrift.
29  *
30  */
31 public class TBinaryProtocol extends TProtocol {
32 
33   protected static final int VERSION_MASK = 0xffff0000;
34   protected static final int VERSION_1 = 0x80010000;
35 
36   protected boolean strictRead_ = false;
37   protected boolean strictWrite_ = true;
38 
39   /**
40    * Factory
41    */
42   public static class Factory implements TProtocolFactory {
43     protected boolean strictRead_ = false;
44     protected boolean strictWrite_ = true;
45 
Factory()46     public Factory() {
47       this(false, true);
48     }
49 
Factory(boolean strictRead, boolean strictWrite)50     public Factory(boolean strictRead, boolean strictWrite) {
51       strictRead_ = strictRead;
52       strictWrite_ = strictWrite;
53     }
54 
getProtocol(TTransport trans)55     public TProtocol getProtocol(TTransport trans) {
56       return new TBinaryProtocol(trans, strictRead_, strictWrite_);
57     }
58   }
59 
60   /**
61    * Constructor
62    */
TBinaryProtocol(TTransport trans)63   public TBinaryProtocol(TTransport trans) {
64     this(trans, false, true);
65   }
66 
TBinaryProtocol(TTransport trans, boolean strictRead, boolean strictWrite)67   public TBinaryProtocol(TTransport trans, boolean strictRead, boolean strictWrite) {
68     super(trans);
69     strictRead_ = strictRead;
70     strictWrite_ = strictWrite;
71   }
72 
writeMessageBegin(TMessage message)73   public void writeMessageBegin(TMessage message) throws TException {
74     if (strictWrite_) {
75       int version = VERSION_1 | message.type;
76       writeI32(version);
77       writeString(message.name);
78       writeI32(message.seqid);
79     } else {
80       writeString(message.name);
81       writeByte(message.type);
82       writeI32(message.seqid);
83     }
84   }
85 
writeMessageEnd()86   public void writeMessageEnd() {}
87 
writeStructBegin(TStruct struct)88   public void writeStructBegin(TStruct struct) {}
89 
writeStructEnd()90   public void writeStructEnd() {}
91 
writeFieldBegin(TField field)92   public void writeFieldBegin(TField field) throws TException {
93     writeByte(field.type);
94     writeI16(field.id);
95   }
96 
writeFieldEnd()97   public void writeFieldEnd() {}
98 
writeFieldStop()99   public void writeFieldStop() throws TException {
100     writeByte(TType.STOP);
101   }
102 
writeMapBegin(TMap map)103   public void writeMapBegin(TMap map) throws TException {
104     writeByte(map.keyType);
105     writeByte(map.valueType);
106     writeI32(map.size);
107   }
108 
writeMapEnd()109   public void writeMapEnd() {}
110 
writeListBegin(TList list)111   public void writeListBegin(TList list) throws TException {
112     writeByte(list.elemType);
113     writeI32(list.size);
114   }
115 
writeListEnd()116   public void writeListEnd() {}
117 
writeSetBegin(TSet set)118   public void writeSetBegin(TSet set) throws TException {
119     writeByte(set.elemType);
120     writeI32(set.size);
121   }
122 
writeSetEnd()123   public void writeSetEnd() {}
124 
writeBool(boolean b)125   public void writeBool(boolean b) throws TException {
126     writeByte(b ? (byte)1 : (byte)0);
127   }
128 
129   private byte [] bout = new byte[1];
writeByte(byte b)130   public void writeByte(byte b) throws TException {
131     bout[0] = b;
132     trans_.write(bout, 0, 1);
133   }
134 
135   private byte[] i16out = new byte[2];
writeI16(short i16)136   public void writeI16(short i16) throws TException {
137     i16out[0] = (byte)(0xff & (i16 >> 8));
138     i16out[1] = (byte)(0xff & (i16));
139     trans_.write(i16out, 0, 2);
140   }
141 
142   private byte[] i32out = new byte[4];
writeI32(int i32)143   public void writeI32(int i32) throws TException {
144     i32out[0] = (byte)(0xff & (i32 >> 24));
145     i32out[1] = (byte)(0xff & (i32 >> 16));
146     i32out[2] = (byte)(0xff & (i32 >> 8));
147     i32out[3] = (byte)(0xff & (i32));
148     trans_.write(i32out, 0, 4);
149   }
150 
151   private byte[] i64out = new byte[8];
writeI64(long i64)152   public void writeI64(long i64) throws TException {
153     i64out[0] = (byte)(0xff & (i64 >> 56));
154     i64out[1] = (byte)(0xff & (i64 >> 48));
155     i64out[2] = (byte)(0xff & (i64 >> 40));
156     i64out[3] = (byte)(0xff & (i64 >> 32));
157     i64out[4] = (byte)(0xff & (i64 >> 24));
158     i64out[5] = (byte)(0xff & (i64 >> 16));
159     i64out[6] = (byte)(0xff & (i64 >> 8));
160     i64out[7] = (byte)(0xff & (i64));
161     trans_.write(i64out, 0, 8);
162   }
163 
writeDouble(double dub)164   public void writeDouble(double dub) throws TException {
165     writeI64(Double.doubleToLongBits(dub));
166   }
167 
writeString(String str)168   public void writeString(String str) throws TException {
169     try {
170       byte[] dat = str.getBytes("UTF-8");
171       writeI32(dat.length);
172       trans_.write(dat, 0, dat.length);
173     } catch (UnsupportedEncodingException uex) {
174       throw new TException("JVM DOES NOT SUPPORT UTF-8");
175     }
176   }
177 
writeBinary(byte[] bin)178   public void writeBinary(byte[] bin) throws TException {
179     writeI32(bin.length);
180     trans_.write(bin, 0, bin.length);
181   }
182 
183   /**
184    * Reading methods.
185    */
186 
readMessageBegin()187   public TMessage readMessageBegin() throws TException {
188     TMessage message = new TMessage();
189 
190     int size = readI32();
191     if (size < 0) {
192       int version = size & VERSION_MASK;
193       if (version != VERSION_1) {
194         throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in readMessageBegin");
195       }
196       message.type = (byte)(size & 0x000000ff);
197       message.name = readString();
198       message.seqid = readI32();
199     } else {
200       if (strictRead_) {
201         throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?");
202       }
203       message.name = readStringBody(size);
204       message.type = readByte();
205       message.seqid = readI32();
206     }
207     return message;
208   }
209 
readMessageEnd()210   public void readMessageEnd() {}
211 
readStructBegin()212   public TStruct readStructBegin() {
213     return new TStruct();
214   }
215 
readStructEnd()216   public void readStructEnd() {}
217 
readFieldBegin()218   public TField readFieldBegin() throws TException {
219     TField field = new TField();
220     field.type = readByte();
221     if (field.type != TType.STOP) {
222       field.id = readI16();
223     }
224     return field;
225   }
226 
readFieldEnd()227   public void readFieldEnd() {}
228 
readMapBegin()229   public TMap readMapBegin() throws TException {
230     TMap map = new TMap();
231     map.keyType = readByte();
232     map.valueType = readByte();
233     map.size = readI32();
234     return map;
235   }
236 
readMapEnd()237   public void readMapEnd() {}
238 
readListBegin()239   public TList readListBegin() throws TException {
240     TList list = new TList();
241     list.elemType = readByte();
242     list.size = readI32();
243     return list;
244   }
245 
readListEnd()246   public void readListEnd() {}
247 
readSetBegin()248   public TSet readSetBegin() throws TException {
249     TSet set = new TSet();
250     set.elemType = readByte();
251     set.size = readI32();
252     return set;
253   }
254 
readSetEnd()255   public void readSetEnd() {}
256 
readBool()257   public boolean readBool() throws TException {
258     return (readByte() == 1);
259   }
260 
261   private byte[] bin = new byte[1];
readByte()262   public byte readByte() throws TException {
263     readAll(bin, 0, 1);
264     return bin[0];
265   }
266 
267   private byte[] i16rd = new byte[2];
readI16()268   public short readI16() throws TException {
269     readAll(i16rd, 0, 2);
270     return
271       (short)
272       (((i16rd[0] & 0xff) << 8) |
273        ((i16rd[1] & 0xff)));
274   }
275 
276   private byte[] i32rd = new byte[4];
readI32()277   public int readI32() throws TException {
278     readAll(i32rd, 0, 4);
279     return
280       ((i32rd[0] & 0xff) << 24) |
281       ((i32rd[1] & 0xff) << 16) |
282       ((i32rd[2] & 0xff) <<  8) |
283       ((i32rd[3] & 0xff));
284   }
285 
286   private byte[] i64rd = new byte[8];
readI64()287   public long readI64() throws TException {
288     readAll(i64rd, 0, 8);
289     return
290       ((long)(i64rd[0] & 0xff) << 56) |
291       ((long)(i64rd[1] & 0xff) << 48) |
292       ((long)(i64rd[2] & 0xff) << 40) |
293       ((long)(i64rd[3] & 0xff) << 32) |
294       ((long)(i64rd[4] & 0xff) << 24) |
295       ((long)(i64rd[5] & 0xff) << 16) |
296       ((long)(i64rd[6] & 0xff) <<  8) |
297       ((long)(i64rd[7] & 0xff));
298   }
299 
readDouble()300   public double readDouble() throws TException {
301     return Double.longBitsToDouble(readI64());
302   }
303 
readString()304   public String readString() throws TException {
305     int size = readI32();
306     return readStringBody(size);
307   }
308 
readStringBody(int size)309   public String readStringBody(int size) throws TException {
310     try {
311       byte[] buf = new byte[size];
312       trans_.readAll(buf, 0, size);
313       return new String(buf, "UTF-8");
314     } catch (UnsupportedEncodingException uex) {
315       throw new TException("JVM DOES NOT SUPPORT UTF-8");
316     }
317   }
318 
readBinary()319   public byte[] readBinary() throws TException {
320     int size = readI32();
321     byte[] buf = new byte[size];
322     trans_.readAll(buf, 0, size);
323     return buf;
324   }
325 
readAll(byte[] buf, int off, int len)326   private int readAll(byte[] buf, int off, int len) throws TException {
327     return trans_.readAll(buf, off, len);
328   }
329 }
330