package edu.uw.zookeeper.netty; import static com.google.common.base.Preconditions.checkNotNull; import java.io.IOException; import org.apache.logging.log4j.Logger; import edu.uw.zookeeper.net.Encoder; import edu.uw.zookeeper.net.LoggingMarker; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPipeline; import io.netty.handler.codec.MessageToByteEncoder; public class EncoderHandler<I> extends MessageToByteEncoder<I> { public static ChannelPipeline toPipeline( EncoderHandler<?> handler, ChannelPipeline pipeline) { return pipeline.addFirst(EncoderHandler.class.getName(), handler); } public static EncoderHandler<?> fromPipeline(ChannelPipeline pipeline) { return (EncoderHandler<?>) pipeline.get(EncoderHandler.class.getName()); } public static <I> EncoderHandler<I> withEncoder( Encoder<I, ? extends I> encoder, Logger logger) { return new EncoderHandler<I>(encoder.encodeType(), encoder, logger); } private final Logger logger; private final Encoder<? super I, ?> encoder; protected EncoderHandler( Class<? extends I> type, Encoder<? super I, ?> encoder, Logger logger) { super(type, true); this.logger = checkNotNull(logger); this.encoder = checkNotNull(encoder); } @Override public void read(ChannelHandlerContext ctx) throws Exception { // trigger a re-read of any accumulated buffers final ChannelPipeline pipeline = ctx.pipeline(); DecoderHandler decoder = DecoderHandler.fromPipeline(pipeline); if ((decoder != null) && (decoder.actualReadableBytes() > 0)) { // this is hopefully probably safe ?? ctx.channel().eventLoop().execute(new Runnable() { @Override public void run() { pipeline.fireChannelRead(Unpooled.EMPTY_BUFFER); pipeline.fireChannelReadComplete(); } }); } super.read(ctx); } @Override protected void encode(ChannelHandlerContext ctx, I message, ByteBuf output) throws IOException { if (logger.isTraceEnabled()) { logger.trace(LoggingMarker.NET_MARKER.get(), "ENCODING {} ({})", message, ctx.channel()); } encoder.encode(message, output); } }