package com.sdyc.ndmp.protobuf.serializer;
import com.google.protobuf.GeneratedMessage;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
/**
*
*
* Created by IntelliJ IDEA.
* User: zhenqin
* Date: 14-7-28
* Time: 下午3:36
* To change this template use File | Settings | File Templates.
*
*
*
* @author zhenqin
*/
public class ProtobufSerializer implements Serializer {
private static final long serialVersionUID = 1L;
/**
* 字符编码
*/
protected String charset = "UTF-8";
/**
* 内部缓存
*/
protected final static Map, Method>
CLASS_METHOD_MAP = new HashMap, Method>(3);
public ProtobufSerializer() {
}
public ProtobufSerializer(String charset) {
this.charset = charset;
}
@Override
public byte[] serialize(GeneratedMessage o) {
if (o == null) {
return null;
}
byte[] bytes = o.toByteArray();
String clazz = o.getClass().getName();
byte[] bytes1 = clazz.getBytes(Charset.forName(charset));
ByteBuf channelBuffer = Unpooled.buffer(4 + bytes.length + bytes1.length);
channelBuffer.writeInt(bytes1.length);
channelBuffer.writeBytes(bytes1);
channelBuffer.writeBytes(bytes);
return channelBuffer.array();
}
@Override
public GeneratedMessage deserialize(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return null;
}
ByteBuf channelBuffer = Unpooled.wrappedBuffer(bytes);
channelBuffer.resetReaderIndex();
int classNameLength = channelBuffer.readInt();
ByteBuf classBuf = channelBuffer.readBytes(classNameLength);
String clazzName = classBuf.toString(Charset.forName(charset));
ByteBuf objectBuf = channelBuffer.readBytes(channelBuffer.readableBytes());
// 检查一下Netty Protobuf解码器是怎么写的
try {
return reflact(clazzName, objectBuf.array());
} catch (ClassNotFoundException e) {
throw new IllegalStateException("class: " + clazzName + " not found!", e);
} catch (NoSuchMethodException e) {
throw new IllegalStateException("class: " + clazzName + " has not method: parseFrom(byte[]).", e);
} catch (Exception e) {
throw new IllegalStateException("reflection error!", e);
}
}
protected static GeneratedMessage reflact(String clazz, byte[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class> aClass = Class.forName(clazz);
Method method = CLASS_METHOD_MAP.get(aClass);
if (method == null) {
method = aClass.getMethod("parseFrom", byte[].class);
CLASS_METHOD_MAP.put(aClass, method);
}
return (GeneratedMessage) method.invoke(null, args);
}
public String getCharset() {
return charset;
}
public void setCharset(String charset) {
this.charset = charset;
}
}