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