package org.handwerkszeug.riak.transport.protobuf.internal; import java.io.IOException; import org.handwerkszeug.riak.nls.Messages; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBufferInputStream; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandler.Sharable; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.handler.codec.oneone.OneToOneDecoder; import com.google.protobuf.MessageLite; /** * @author taichi * @see <a href="http://wiki.basho.com/PBC-API.html">PBC-API</a> */ @Sharable public class RiakProtoBufDecoder extends OneToOneDecoder { public RiakProtoBufDecoder() { } @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { if (msg instanceof ChannelBuffer) { ChannelBuffer buffer = (ChannelBuffer) msg; int length = buffer.readInt(); if (length < 1) { throw new IllegalStateException(String.format( Messages.UnsupportedContentLength, length)); } length -= 1; byte code = buffer.readByte(); MessageCodes mc = MessageCodes.valueOf(code); MessageLite proto = mc.getPrototype(); if (proto != null) { MessageLite.Builder builder = mergeFrom( proto.newBuilderForType(), buffer, length); MessageLite newone = builder.build(); return newone; } else { return mc; } } return msg; } protected MessageLite.Builder mergeFrom(MessageLite.Builder builder, ChannelBuffer buffer, int length) throws IOException { if (buffer.hasArray()) { final int offset = buffer.readerIndex(); return builder.mergeFrom(buffer.array(), buffer.arrayOffset() + offset, length); } else { return builder.mergeFrom(new ChannelBufferInputStream(buffer)); } } }