Java tutorial
/* * Copyright(C) 2011-2012 Alibaba Group Holding Limited * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Authors: * wentong <wentong@taobao.com> */ package com.taobao.tdhs.client.protocol; import com.taobao.tdhs.client.common.TDHSCommon; import com.taobao.tdhs.client.exception.TDHSEncodeException; import com.taobao.tdhs.client.packet.BasePacket; import com.taobao.tdhs.client.request.Request; import com.taobao.tdhs.client.request.RequestWithCharset; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Collection; /** * @author <a href="mailto:wentong@taobao.com"></a> * @since 11-12-2 ?11:17 */ public class TDHSProtocolBinary implements TDHSProtocol { private Logger logger = LoggerFactory.getLogger(this.getClass()); public BasePacket shakeHandPacket(int timeOut, @Nullable String readCode, @Nullable String writeCode) { try { ByteArrayOutputStream out = new ByteArrayOutputStream(12 + 2 + 200); out.write("TDHS".getBytes()); writeInt32ToStream(1, out);//? writeInt32ToStream(timeOut, out);// writeToStream(readCode, out, null); //read code writeToStream(writeCode, out, null);//write code return new BasePacket(TDHSCommon.RequestType.SHAKE_HAND, 0, out.toByteArray()); } catch (IOException e) { assert false; //?? logger.error("shakeHandPacket failed!", e); return null; } } public byte[] encode(RequestWithCharset o) throws TDHSEncodeException { try { o.isValid(getProtocolVersion()); ByteArrayOutputStream out = new ByteArrayOutputStream(2 * 1024); encodeRequest(o, out, o.getCharsetName()); return out.toByteArray(); } catch (IllegalAccessException e) { throw new TDHSEncodeException(e); } catch (IOException e) { throw new TDHSEncodeException(e); } } public TDHSCommon.ProtocolVersion getProtocolVersion() { return TDHSCommon.ProtocolVersion.V1; } protected static void encodeRequest(Request o, ByteArrayOutputStream out, String charsetName) throws IllegalAccessException, IOException, TDHSEncodeException { for (Field f : o.getClass().getDeclaredFields()) { if (!Modifier.isPublic(f.getModifiers())) { f.setAccessible(true); } Object v = f.get(o); if (v instanceof Request) { encodeRequest((Request) v, out, charsetName); } else if (f.getName().startsWith("_")) { writeObjectToStream(v, out, f.getName(), charsetName); } } } protected static void writeObjectToStream(Object o, ByteArrayOutputStream out, String fieldName, String charsetName) throws IOException, TDHSEncodeException, IllegalAccessException { if (o == null || o instanceof String) { writeToStream((String) o, out, charsetName); } else if (o instanceof byte[]) { writeToStream((byte[]) o, out); } else if (o instanceof Integer) { if (fieldName.startsWith("____")) { writeInt8ToStream((Integer) o, out); } else { writeInt32ToStream((Integer) o, out); } } else if (o instanceof Collection) { writeToStream(((Collection) o).toArray(), out, charsetName); } else if (o instanceof Object[]) { writeToStream((Object[]) o, out, charsetName); } else { throw new TDHSEncodeException("unknown type!"); } } protected static void writeToStream(String v, ByteArrayOutputStream out, @Nullable String charsetName) throws IOException { if (v == null) { writeInt32ToStream(0, out); } else { byte[] sb = StringUtils.isNotBlank(charsetName) ? v.getBytes(charsetName) : v.getBytes(); writeInt32ToStream(sb.length + 1, out); out.write(sb); out.write(0); } } protected static void writeToStream(byte[] v, ByteArrayOutputStream out) throws IOException { if (v == null) { writeInt32ToStream(0, out); } else { writeInt32ToStream(v.length + 1, out); out.write(v); out.write(0); //???0,byte[]?0 } } protected static void writeToStream(Object[] array, ByteArrayOutputStream out, String charsetName) throws IOException, TDHSEncodeException, IllegalAccessException { writeInt32ToStream(array.length, out); for (Object o : array) { if (o == null || o instanceof String) { writeToStream((String) o, out, charsetName); } else if (o instanceof byte[]) { writeToStream((byte[]) o, out); } else if (o instanceof Integer) { writeInt32ToStream((Integer) o, out); } else if (o instanceof Request) { encodeRequest((Request) o, out, charsetName); } else if (o instanceof Collection) { writeToStream(((Collection) o).toArray(), out, charsetName); } else if (o instanceof Object[]) { writeToStream((Object[]) o, out, charsetName); } else { throw new TDHSEncodeException("unknown type!"); } } } protected static void writeInt32ToStream(int v, ByteArrayOutputStream out) { for (int i = 3; i >= 0; i--) { out.write((byte) ((v >>> (8 * i)) & 0XFF)); } } protected static void writeInt8ToStream(int v, ByteArrayOutputStream out) { out.write((byte) (v & 0XFF)); } }