package com.dianping.pigeon.remoting.netty.codec; import com.dianping.pigeon.log.LoggerLoader; import com.dianping.pigeon.remoting.common.codec.SerializerFactory; import com.dianping.pigeon.remoting.common.domain.InvocationResponse; import com.dianping.pigeon.remoting.common.domain.InvocationSerializable; import com.dianping.pigeon.remoting.common.domain.generic.UnifiedInvocation; import com.dianping.pigeon.remoting.common.exception.SerializationException; import com.dianping.pigeon.remoting.common.util.Constants; import com.dianping.pigeon.remoting.provider.util.ProviderUtils; import com.dianping.pigeon.log.Logger; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBufferOutputStream; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; import java.io.IOException; import java.io.OutputStream; import static org.jboss.netty.buffer.ChannelBuffers.dynamicBuffer; /** * @author qi.yin * 2016/06/21 上午9:55. */ public abstract class AbstractEncoder extends OneToOneEncoder { private static final Logger logger = LoggerLoader.getLogger(AbstractEncoder.class); public abstract void serialize(byte serializer, OutputStream os, Object obj, Channel channel) throws IOException; @Override public Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { if (msg instanceof InvocationSerializable) { InvocationSerializable _msg = (InvocationSerializable) msg; try { ChannelBuffer frame; CodecEvent codecEvent; if (msg instanceof UnifiedInvocation) { frame = _doEncode(channel, (UnifiedInvocation) _msg); codecEvent = new CodecEvent(frame, true); } else { frame = doEncode(channel, _msg); codecEvent = new CodecEvent(frame, false); } return codecEvent; } catch (Exception e) { SerializationException se = new SerializationException(e); try { doFailResponse(ctx, channel, ProviderUtils.createThrowableResponse(_msg, _msg.getSerialize(), se)); } catch (Throwable t) { } logger.error(e.getMessage(), se); throw se; } } else { throw new SerializationException("Invalid message format"); } } protected ChannelBuffer doEncode(Channel channel, InvocationSerializable msg) throws IOException { ChannelBufferOutputStream os = new ChannelBufferOutputStream(dynamicBuffer(CodecConstants.ESTIMATED_LENGTH, channel.getConfig().getBufferFactory())); //magic os.write(CodecConstants.MAGIC); //serialize os.writeByte(msg.getSerialize()); //bodyLength os.writeInt(Integer.MAX_VALUE); serialize(msg.getSerialize(), os, msg, channel); //body ChannelBuffer frame = os.buffer(); //sequence frame.writeLong(msg.getSequence()); //expand frame.writeBytes(CodecConstants.EXPAND); //bodyLength frame.setInt(CodecConstants.HEAD_LENGTH, frame.readableBytes() - CodecConstants.FRONT_LENGTH); doAfter(msg, frame.readableBytes()); return frame; } protected ChannelBuffer _doEncode(Channel channel, UnifiedInvocation msg) throws IOException { ChannelBufferOutputStream os = new ChannelBufferOutputStream(dynamicBuffer(CodecConstants.ESTIMATED_LENGTH, channel.getConfig().getBufferFactory())); //magic os.write(CodecConstants._MAGIC); os.writeByte(msg.getProtocolVersion()); //serialize byte serialize = SerializerFactory.convertToUnifiedSerialize(msg.getSerialize()); //serialize os.writeByte(serialize); //totalLength os.writeInt(Integer.MAX_VALUE); serialize(msg.getSerialize(), os, msg, channel); ChannelBuffer frame = os.buffer(); //totalLength frame.setInt(CodecConstants._HEAD_LENGTH, frame.readableBytes() - CodecConstants._FRONT_LENGTH_); doAfter(msg, frame.readableBytes()); return frame; } private void doAfter(Object msg, int frameLength) throws IOException { if (msg instanceof InvocationSerializable) { InvocationSerializable msg_ = (InvocationSerializable) msg; int msgType = msg_.getMessageType(); if (msgType == Constants.MESSAGE_TYPE_SERVICE && frameLength > 0) { msg_.setSize(frameLength); } } } public abstract void doFailResponse(ChannelHandlerContext ctx, Channel channel, InvocationResponse response); }