Add a lot of javadocs to make usage more clear
This commit is contained in:
parent
b004066f37
commit
8a7bc2c606
@ -15,6 +15,9 @@
|
||||
*/
|
||||
package io.netty.buffer;
|
||||
|
||||
/**
|
||||
* A buffer to operate on
|
||||
*/
|
||||
public interface Buf {
|
||||
/**
|
||||
* The BufType which will be handled by the Buf implementation
|
||||
|
@ -26,6 +26,9 @@ import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
|
||||
/**
|
||||
* Utility class for operate on a {@link ByteBuf}
|
||||
*/
|
||||
public final class ByteBufUtil {
|
||||
|
||||
private static final char[] HEXDUMP_TABLE = new char[256 * 4];
|
||||
|
@ -20,30 +20,171 @@ import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link ByteBuf} which is composed out of other {@link ByteBuf}s.
|
||||
*/
|
||||
public interface CompositeByteBuf extends ByteBuf, Iterable<ByteBuf> {
|
||||
|
||||
/**
|
||||
* Add the given {@link ByteBuf}.
|
||||
*
|
||||
* @param buffer the {@link ByteBuf} to add
|
||||
* @return self this instance
|
||||
*/
|
||||
CompositeByteBuf addComponent(ByteBuf buffer);
|
||||
|
||||
/**
|
||||
* Add the given {@link ByteBuf} on the specific index.
|
||||
*
|
||||
* @param cIndex
|
||||
* the index on which the {@link ByteBuf} will be added
|
||||
* @param buffer
|
||||
* the {@link ByteBuf} to add
|
||||
* @return self
|
||||
* this instance
|
||||
* @thows {@link IndexOutOfBoundsException}
|
||||
* if the index is invalid
|
||||
*/
|
||||
CompositeByteBuf addComponent(int cIndex, ByteBuf buffer);
|
||||
|
||||
/**
|
||||
* Add the given {@link ByteBuf}s.
|
||||
*
|
||||
* @param buffers the {@link ByteBuf}s to add
|
||||
* @return self this instance
|
||||
*/
|
||||
CompositeByteBuf addComponents(ByteBuf... buffers);
|
||||
|
||||
/**
|
||||
* Add the given {@link ByteBuf}s.
|
||||
*
|
||||
* @param buffers the {@link ByteBuf}s to add
|
||||
* @return self this instance
|
||||
*/
|
||||
CompositeByteBuf addComponents(Iterable<ByteBuf> buffers);
|
||||
|
||||
/**
|
||||
* Add the given {@link ByteBuf}s on the specific index
|
||||
*
|
||||
* @param cIndex
|
||||
* the index on which the {@link ByteBuf} will be added.
|
||||
* @param buffers
|
||||
* the {@link ByteBuf}s to add
|
||||
* @return self
|
||||
* this instance
|
||||
* @thows {@link IndexOutOfBoundsException}
|
||||
* if the index is invalid
|
||||
*
|
||||
*/
|
||||
CompositeByteBuf addComponents(int cIndex, ByteBuf... buffers);
|
||||
|
||||
/**
|
||||
* Add the given {@link ByteBuf}s on the specific index
|
||||
*
|
||||
* @param cIndex
|
||||
* the index on which the {@link ByteBuf} will be added.
|
||||
* @param buffers
|
||||
* the {@link ByteBuf}s to add
|
||||
* @return self
|
||||
* this instance
|
||||
* @thows {@link IndexOutOfBoundsException}
|
||||
* if the index is invalid
|
||||
*/
|
||||
CompositeByteBuf addComponents(int cIndex, Iterable<ByteBuf> buffers);
|
||||
|
||||
/**
|
||||
* Remove the {@link ByteBuf} from the given index.
|
||||
*
|
||||
* @param cIndex
|
||||
* the index on from which the {@link ByteBuf} will be remove
|
||||
* @return self
|
||||
* this instance
|
||||
* @thows {@link IndexOutOfBoundsException}
|
||||
* if the index is invalid
|
||||
*/
|
||||
CompositeByteBuf removeComponent(int cIndex);
|
||||
|
||||
/**
|
||||
* Remove the number of {@link ByteBuf}s starting from the given index.
|
||||
*
|
||||
* @param cIndex
|
||||
* the index on which the {@link ByteBuf}s will be started to removed
|
||||
* @param numComponents
|
||||
* the number of components to remove
|
||||
* @return self
|
||||
* this instance
|
||||
* @thows {@link IndexOutOfBoundsException}
|
||||
* if the index is invalid
|
||||
*/
|
||||
CompositeByteBuf removeComponents(int cIndex, int numComponents);
|
||||
|
||||
/**
|
||||
* Return the current number of {@link ByteBuf}'s that are composed in this instance
|
||||
*/
|
||||
int numComponents();
|
||||
|
||||
/**
|
||||
* Return the max number of {@link ByteBuf}'s that are composed in this instance
|
||||
*/
|
||||
int maxNumComponents();
|
||||
|
||||
/**
|
||||
* Return the {@link ByteBuf} on the specified index
|
||||
*
|
||||
* @param cIndex
|
||||
* the index for which the {@link ByteBuf} should be returned
|
||||
* @return buf
|
||||
* the {@link ByteBuf} on the specified index
|
||||
* @thows {@link IndexOutOfBoundsException}
|
||||
* if the index is invalid
|
||||
*/
|
||||
ByteBuf component(int cIndex);
|
||||
|
||||
/**
|
||||
* Return the {@link ByteBuf} on the specified index
|
||||
*
|
||||
* @param offset
|
||||
* the offset for which the {@link ByteBuf} should be returned
|
||||
* @return buf
|
||||
* the {@link ByteBuf} on the specified index
|
||||
* @thows {@link IndexOutOfBoundsException}
|
||||
* if the offset is invalid
|
||||
*/
|
||||
ByteBuf componentAtOffset(int offset);
|
||||
|
||||
/**
|
||||
* Discard all {@link ByteBuf}s which are read.
|
||||
*
|
||||
* @return self this instance
|
||||
*/
|
||||
CompositeByteBuf discardReadComponents();
|
||||
|
||||
/**
|
||||
* Consolidate the composed {@link ByteBuf}s
|
||||
*
|
||||
* @return self this instance
|
||||
*/
|
||||
CompositeByteBuf consolidate();
|
||||
|
||||
/**
|
||||
* Consolidate the composed {@link ByteBuf}s
|
||||
*
|
||||
* @param cIndex
|
||||
* the index on which to start to compose
|
||||
* @param numComponents
|
||||
* the number of components to compose
|
||||
* @return self
|
||||
* this instance
|
||||
* @thows {@link IndexOutOfBoundsException}
|
||||
* if the offset is invalid
|
||||
*/
|
||||
CompositeByteBuf consolidate(int cIndex, int numComponents);
|
||||
|
||||
/**
|
||||
* Return the index for the given offset
|
||||
*/
|
||||
int toComponentIndex(int offset);
|
||||
|
||||
int toByteIndex(int cIndex);
|
||||
|
||||
/**
|
||||
|
@ -19,6 +19,10 @@ import java.util.ArrayDeque;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Default {@link MessageBuf} implementation
|
||||
*
|
||||
*/
|
||||
final class DefaultMessageBuf<T> extends ArrayDeque<T> implements MessageBuf<T> {
|
||||
|
||||
private static final long serialVersionUID = 1229808623624907552L;
|
||||
|
@ -19,11 +19,26 @@ import java.util.Collection;
|
||||
import java.util.Queue;
|
||||
|
||||
/**
|
||||
* Buf which operates on messages
|
||||
* Buf which operates on messages.
|
||||
*
|
||||
* @param <T>
|
||||
* @param <T> the type of the messages that are hold by this {@link MessageBuf}
|
||||
*/
|
||||
public interface MessageBuf<T> extends Buf, Queue<T> {
|
||||
|
||||
/**
|
||||
* Drain the content of te {@link MessageBuf} to the given {@link Collection}.
|
||||
*
|
||||
* @param c the {@link Collection} to drain the content to
|
||||
* @return number the number of objects which was transfered
|
||||
*/
|
||||
int drainTo(Collection<? super T> c);
|
||||
|
||||
/**
|
||||
* Drain the content of te {@link MessageBuf} to the given {@link Collection}.
|
||||
*
|
||||
* @param c the {@link Collection} to drain the content to
|
||||
* @param maxElements the max number of elements to drain
|
||||
* @return number the number of objects which was transfered
|
||||
*/
|
||||
int drainTo(Collection<? super T> c, int maxElements);
|
||||
}
|
||||
|
@ -23,6 +23,36 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundByteHandler;
|
||||
import io.netty.channel.ChannelOutboundByteHandler;
|
||||
|
||||
/**
|
||||
* A Codec for on-the-fly encoding/decoding of bytes.
|
||||
*
|
||||
* This can be though of an combination of {@link ByteToByteDecoder} and {@link ByteToByteEncoder}.
|
||||
*
|
||||
* Here is an example of a {@link ByteToByteCodec} which just square {@link Integer} read from a {@link ByteBuf}.
|
||||
* <pre>
|
||||
* public class SquareCodec extends {@link ByteToByteCodec} {
|
||||
* {@code @Override}
|
||||
* public void decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link ByteBuf} out)
|
||||
* throws {@link Exception} {
|
||||
* if (in.readableBytes() < 4) {
|
||||
* return;
|
||||
* }
|
||||
* int value = in.readInt();
|
||||
* out.writeInt(value * value);
|
||||
* }
|
||||
*
|
||||
* {@code @Overrride}
|
||||
* public void encode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link ByteBuf} out)
|
||||
* throws {@link Exception} {
|
||||
* if (in.readableBytes() < 4) {
|
||||
* return;
|
||||
* }
|
||||
* int value = in.readInt();
|
||||
* out.writeInt(value / value);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public abstract class ByteToByteCodec
|
||||
extends ChannelHandlerAdapter
|
||||
implements ChannelInboundByteHandler, ChannelOutboundByteHandler {
|
||||
@ -76,10 +106,16 @@ public abstract class ByteToByteCodec
|
||||
encoder.freeOutboundBuffer(ctx, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see {@link ByteToByteEncoder#encode(ChannelHandlerContext, ByteBuf, ByteBuf)}
|
||||
*/
|
||||
public abstract void encode(
|
||||
ChannelHandlerContext ctx,
|
||||
ByteBuf in, ByteBuf out) throws Exception;
|
||||
|
||||
/**
|
||||
* @see {@link ByteToByteDecoder#decode(ChannelHandlerContext, ByteBuf, ByteBuf)}
|
||||
*/
|
||||
public abstract void decode(
|
||||
ChannelHandlerContext ctx,
|
||||
ByteBuf in, ByteBuf out) throws Exception;
|
||||
|
@ -19,6 +19,29 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundByteHandlerAdapter;
|
||||
|
||||
/**
|
||||
* {@link ChannelInboundByteHandlerAdapter} which decodes bytes in a stream-like fashion from one {@link ByteBuf} to an
|
||||
* other.
|
||||
*
|
||||
* This kind of decoder is often useful for doing on-the-fly processiing like i.e. compression.
|
||||
*
|
||||
* But you can also do other things with it. For example here is an implementation which reads {@link Integer}s from
|
||||
* the input {@link ByteBuf} and square them before write them to the output {@link ByteBuf}.
|
||||
*
|
||||
* <pre>
|
||||
* public class SquareDecoder extends {@link ByteToByteDecoder} {
|
||||
* {@code @Override}
|
||||
* public void decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link ByteBuf} out)
|
||||
* throws {@link Exception} {
|
||||
* if (in.readableBytes() < 4) {
|
||||
* return;
|
||||
* }
|
||||
* int value = in.readInt();
|
||||
* out.writeInt(value * value);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter {
|
||||
|
||||
@Override
|
||||
@ -52,6 +75,9 @@ public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter
|
||||
ctx.fireChannelInactive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the {@link #decode(ChannelHandlerContext, ByteBuf, ByteBuf)} method until it is done.
|
||||
*/
|
||||
private void callDecode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) {
|
||||
int oldOutSize = out.readableBytes();
|
||||
while (in.readable()) {
|
||||
@ -76,8 +102,24 @@ public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the from one {@link ByteBuf} to an other. This method will be called till either the input
|
||||
* {@link ByteBuf} has nothing to read anymore or till nothing was read from the input {@link ByteBuf}.
|
||||
*
|
||||
* @param ctx the {@link ChannelHandlerContext} which this {@link ByteToByteDecoder} belongs to
|
||||
* @param in the {@link ByteBuf} from which to read data
|
||||
* @param out the {@link ByteBuf} to which the decoded data will be written
|
||||
* @throws Exception is thrown if an error accour
|
||||
*/
|
||||
public abstract void decode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception;
|
||||
|
||||
/**
|
||||
* Is called one last time when the {@link ChannelHandlerContext} goes in-active. Which means the
|
||||
* {@link #channelInactive(ChannelHandlerContext)} was triggered.
|
||||
*
|
||||
* By default this will just call {@link #decode(ChannelHandlerContext, ByteBuf, ByteBuf)} but sub-classes may
|
||||
* override this for some special cleanup operation.
|
||||
*/
|
||||
public void decodeLast(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception {
|
||||
decode(ctx, in, out);
|
||||
}
|
||||
|
@ -20,6 +20,29 @@ import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOutboundByteHandlerAdapter;
|
||||
|
||||
/**
|
||||
* {@link ChannelOutboundByteHandlerAdapter} which encodes bytes in a stream-like fashion from one {@link ByteBuf} to an
|
||||
* other.
|
||||
*
|
||||
* This kind of decoder is often useful for doing on-the-fly processing like i.e. compression.
|
||||
*
|
||||
* But you can also do other things with it. For example here is an implementation which reads {@link Integer}s from
|
||||
* the input {@link ByteBuf} and square them before write them to the output {@link ByteBuf}.
|
||||
*
|
||||
* <pre>
|
||||
* public class SquareEncoder extends {@link ByteToByteEncoder} {
|
||||
* {@code @Override}
|
||||
* public void encode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link ByteBuf} out)
|
||||
* throws {@link Exception} {
|
||||
* if (in.readableBytes() < 4) {
|
||||
* return;
|
||||
* }
|
||||
* int value = in.readInt();
|
||||
* out.writeInt(value * value);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public abstract class ByteToByteEncoder extends ChannelOutboundByteHandlerAdapter {
|
||||
|
||||
@Override
|
||||
@ -47,5 +70,14 @@ public abstract class ByteToByteEncoder extends ChannelOutboundByteHandlerAdapte
|
||||
ctx.flush(future);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the from one {@link ByteBuf} to an other. This method will be called till either the input
|
||||
* {@link ByteBuf} has nothing to read anymore or till nothing was read from the input {@link ByteBuf}.
|
||||
*
|
||||
* @param ctx the {@link ChannelHandlerContext} which this {@link ByteToByteDecoder} belongs to
|
||||
* @param in the {@link ByteBuf} from which to read data
|
||||
* @param out the {@link ByteBuf} to which the decoded data will be written
|
||||
* @throws Exception is thrown if an error accour
|
||||
*/
|
||||
public abstract void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception;
|
||||
}
|
||||
|
@ -22,6 +22,23 @@ import io.netty.channel.ChannelInboundByteHandler;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
|
||||
/**
|
||||
* {@link ChannelInboundByteHandler} which decodes bytes in a stream-like fashion from one {@link ByteBuf} to an other
|
||||
* Message type.
|
||||
*
|
||||
* For example here is an implementation which reads all readable bytes from
|
||||
* the input {@link ByteBuf} and create a new {@link ByteBuf}.
|
||||
*
|
||||
* <pre>
|
||||
* public class SquareDecoder extends {@link ByteToMessageDecoder}<{@link ByteBuf}> {
|
||||
* {@code @Override}
|
||||
* public {@link ByteBuf} decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in)
|
||||
* throws {@link Exception} {
|
||||
* return in.readBytes(in.readableBytes());
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public abstract class ByteToMessageDecoder<O>
|
||||
extends ChannelInboundHandlerAdapter implements ChannelInboundByteHandler {
|
||||
|
||||
@ -138,8 +155,26 @@ public abstract class ByteToMessageDecoder<O>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the from one {@link ByteBuf} to an other. This method will be called till either the input
|
||||
* {@link ByteBuf} has nothing to read anymore, till nothing was read from the input {@link ByteBuf} or till
|
||||
* this method returns {@code null}.
|
||||
*
|
||||
* @param ctx the {@link ChannelHandlerContext} which this {@link ByteToByteDecoder} belongs to
|
||||
* @param in the {@link ByteBuf} from which to read data
|
||||
* @return message the message to which the content of the {@link ByteBuf} was decoded, or {@code null} if
|
||||
* there was not enough data left in the {@link ByteBuf} to decode.
|
||||
* @throws Exception is thrown if an error accour
|
||||
*/
|
||||
public abstract O decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception;
|
||||
|
||||
/**
|
||||
* Is called one last time when the {@link ChannelHandlerContext} goes in-active. Which means the
|
||||
* {@link #channelInactive(ChannelHandlerContext)} was triggered.
|
||||
*
|
||||
* By default this will just call {@link #decode(ChannelHandlerContext, ByteBuf)} but sub-classes may
|
||||
* override this for some special cleanup operation.
|
||||
*/
|
||||
public O decodeLast(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
|
||||
return decode(ctx, in);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
package io.netty.handler.codec;
|
||||
|
||||
/**
|
||||
* An {@link Exception} which is thrown when the received frame data could not be decoded by
|
||||
* An {@link DecoderException} which is thrown when the received frame data could not be decoded by
|
||||
* an inbound handler.
|
||||
*
|
||||
* @apiviz.exclude
|
||||
|
@ -16,7 +16,7 @@
|
||||
package io.netty.handler.codec;
|
||||
|
||||
/**
|
||||
* An {@link Exception} which is thrown by an encoder.
|
||||
* An {@link CodecException} which is thrown by a dencoder.
|
||||
*
|
||||
* @apiviz.exclude
|
||||
*/
|
||||
|
@ -39,7 +39,7 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
* | ABC\nDEF\r\n |
|
||||
* +--------------+
|
||||
* </pre>
|
||||
* a {@link DelimiterBasedFrameDecoder}{@code (}{@link Delimiters#lineDelimiter() Delimiters.lineDelimiter()}{@code )}
|
||||
* a {@link DelimiterBasedFrameDecoder}({@link Delimiters#lineDelimiter() Delimiters.lineDelimiter()})
|
||||
* will choose {@code '\n'} as the first delimiter and produce two frames:
|
||||
* <pre>
|
||||
* +-----+-----+
|
||||
|
@ -16,7 +16,7 @@
|
||||
package io.netty.handler.codec;
|
||||
|
||||
/**
|
||||
* An {@link Exception} which is thrown by an encoder.
|
||||
* An {@link CodecException} which is thrown by an encoder.
|
||||
*
|
||||
* @apiviz.exclude
|
||||
*/
|
||||
|
@ -411,14 +411,10 @@ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder<Object> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the sub-region of the specified buffer. This method is called by
|
||||
* {@link #decode(ChannelInboundHandlerContext, ByteBuf)} for each
|
||||
* frame. The default implementation returns a copy of the sub-region.
|
||||
* For example, you could override this method to use an alternative
|
||||
* {@link ByteBufFactory}.
|
||||
* Extract the sub-region of the specified buffer.
|
||||
* <p>
|
||||
* If you are sure that the frame and its content are not accessed after
|
||||
* the current {@link #decode(ChannelInboundHandlerContext, ByteBuf)}
|
||||
* the current {@link #decode(ChannelHandlerContext, ByteBuf)}
|
||||
* call returns, you can even avoid memory copy by returning the sliced
|
||||
* sub-region (i.e. <tt>return buffer.slice(index, length)</tt>).
|
||||
* It's often useful when you convert the extracted frame into an object.
|
||||
|
@ -19,13 +19,10 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* An encoder that prepends the length of the message. The length value is
|
||||
* prepended as a binary form. It is encoded in either big endian or little
|
||||
* endian depending on the default {@link ByteOrder} of the current
|
||||
* {@link ByteBufFactory}.
|
||||
* prepended as a binary form.
|
||||
* <p>
|
||||
* For example, <tt>{@link LengthFieldPrepender}(2)</tt> will encode the
|
||||
* following 12-bytes string:
|
||||
|
@ -22,6 +22,24 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOutboundMessageHandlerAdapter;
|
||||
import io.netty.channel.ChannelHandlerUtil;
|
||||
|
||||
|
||||
/**
|
||||
* {@link ChannelOutboundMessageHandlerAdapter} which encodes message in a stream-like fashion from one message to an
|
||||
* {@link ByteBuf}.
|
||||
*
|
||||
*
|
||||
* Example implementation which encodes {@link Integer}s to a {@link ByteBuf}.
|
||||
*
|
||||
* <pre>
|
||||
* public class IntegerEncoder extends {@link MessageToByteEncoder}<{@link Integer}> {
|
||||
* {@code @Override}
|
||||
* public void encode({@link ChannelHandlerContext} ctx, {@link Integer} msg, {@link ByteBuf} out)
|
||||
* throws {@link Exception} {
|
||||
* out.writeInt(msg);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public abstract class MessageToByteEncoder<I> extends ChannelOutboundMessageHandlerAdapter<I> {
|
||||
|
||||
private final Class<?>[] acceptedMsgTypes;
|
||||
@ -71,5 +89,14 @@ public abstract class MessageToByteEncoder<I> extends ChannelOutboundMessageHand
|
||||
return ChannelHandlerUtil.acceptMessage(acceptedMsgTypes, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a message into a {@link ByteBuf}. This method will be called till the {@link MessageBuf} has
|
||||
* nothing left.
|
||||
*
|
||||
* @param ctx the {@link ChannelHandlerContext} which this {@link MessageToByteEncoder} belongs to
|
||||
* @param msg the message to encode
|
||||
* @param out the {@link ByteBuf} into which the encoded message will be written
|
||||
* @throws Exception is thrown if an error accour
|
||||
*/
|
||||
public abstract void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception;
|
||||
}
|
||||
|
@ -24,6 +24,30 @@ import io.netty.channel.ChannelHandlerUtil;
|
||||
import io.netty.channel.ChannelInboundMessageHandler;
|
||||
import io.netty.channel.ChannelOutboundMessageHandler;
|
||||
|
||||
/**
|
||||
* A Codec for on-the-fly encoding/decoding of message.
|
||||
*
|
||||
* This can be though of an combination of {@link MessageToMessageDecoder} and {@link MessageToMessageEncoder}.
|
||||
*
|
||||
* Here is an example of a {@link MessageToMessageCodec} which just decode from {@link Integer} to {@link Long}
|
||||
* and encode from {@link Long} to {@link Integer}.
|
||||
* <pre>
|
||||
* public class NumberCodec extends
|
||||
* {@link MessageToMessageCodec}<{@link Integer}, {@link Long}, {@link Long}, {@link Integer}> {
|
||||
* {@code @Override}
|
||||
* public {@link Long} decode({@link ChannelHandlerContext} ctx, {@link Integer} msg)
|
||||
* throws {@link Exception} {
|
||||
* return msg.longValue();
|
||||
* }
|
||||
*
|
||||
* {@code @Overrride}
|
||||
* public {@link Integer} encode({@link ChannelHandlerContext} ctx, {@link Long} msg)
|
||||
* throws {@link Exception} {
|
||||
* return msg.intValue();
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public abstract class MessageToMessageCodec<INBOUND_IN, INBOUND_OUT, OUTBOUND_IN, OUTBOUND_OUT>
|
||||
extends ChannelHandlerAdapter
|
||||
implements ChannelInboundMessageHandler<INBOUND_IN>,
|
||||
|
@ -21,12 +21,38 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelHandlerUtil;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelInboundMessageHandler;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
|
||||
/**
|
||||
* {@link ChannelInboundMessageHandler} which decodes from one message to an other message
|
||||
*
|
||||
* For example here is an implementation which decodes a {@link String} to an {@link Integer} which represent
|
||||
* the length of the {@link String}.
|
||||
*
|
||||
* <pre>
|
||||
* public class StringToIntegerDecoder extends
|
||||
* {@link MessageToMessageDecoder}<{@link String},{@link Integer}> {
|
||||
* public StringToIntegerDecoder() {
|
||||
* super(String.class);
|
||||
* }
|
||||
*
|
||||
* {@code @Override}
|
||||
* public {@link Integer} decode({@link ChannelHandlerContext} ctx, {@link String} message)
|
||||
* throws {@link Exception} {
|
||||
* return message.length());
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public abstract class MessageToMessageDecoder<I, O>
|
||||
extends ChannelInboundHandlerAdapter implements ChannelInboundMessageHandler<I> {
|
||||
|
||||
private final Class<?>[] acceptedMsgTypes;
|
||||
|
||||
/**
|
||||
* The types which will be accepted by the decoder. If a received message is an other type it will be just forwared
|
||||
* to the next {@link ChannelInboundMessageHandler} in the {@link ChannelPipeline}
|
||||
*/
|
||||
protected MessageToMessageDecoder(Class<?>... acceptedMsgTypes) {
|
||||
this.acceptedMsgTypes = ChannelHandlerUtil.acceptedMessageTypes(acceptedMsgTypes);
|
||||
}
|
||||
@ -80,12 +106,20 @@ public abstract class MessageToMessageDecoder<I, O>
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if the specified message can be decoded by this decoder.
|
||||
*
|
||||
* @param msg the message
|
||||
*/
|
||||
public boolean isDecodable(Object msg) throws Exception {
|
||||
return ChannelHandlerUtil.acceptMessage(acceptedMsgTypes, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode from one message to an other. This method will be called till either the {@link MessageBuf} has
|
||||
* nothing left or till this method returns {@code null}.
|
||||
*
|
||||
* @param ctx the {@link ChannelHandlerContext} which this {@link MessageToMessageDecoder} belongs to
|
||||
* @param msg the message to decode to an other one
|
||||
* @return message the decoded message or {@code null} if more messages are needed be cause the implementation
|
||||
* needs to do some kind of aggragation
|
||||
* @throws Exception is thrown if an error accour
|
||||
*/
|
||||
public abstract O decode(ChannelHandlerContext ctx, I msg) throws Exception;
|
||||
}
|
||||
|
@ -18,13 +18,39 @@ package io.netty.handler.codec;
|
||||
import io.netty.buffer.MessageBuf;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOutboundMessageHandler;
|
||||
import io.netty.channel.ChannelOutboundMessageHandlerAdapter;
|
||||
import io.netty.channel.ChannelHandlerUtil;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
|
||||
/**
|
||||
* {@link ChannelOutboundMessageHandlerAdapter} which encodes from one message to an other message
|
||||
*
|
||||
* For example here is an implementation which decodes an {@link Integer} to an {@link String}.
|
||||
*
|
||||
* <pre>
|
||||
* public class IntegerToStringEncoder extends
|
||||
* {@link MessageToMessageEncoder}<{@link Integer},{@link String}> {
|
||||
* public StringToIntegerDecoder() {
|
||||
* super(String.class);
|
||||
* }
|
||||
*
|
||||
* {@code @Override}
|
||||
* public {@link String} encode({@link ChannelHandlerContext} ctx, {@link Integer} message)
|
||||
* throws {@link Exception} {
|
||||
* return message.toString();
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public abstract class MessageToMessageEncoder<I, O> extends ChannelOutboundMessageHandlerAdapter<I> {
|
||||
|
||||
private final Class<?>[] acceptedMsgTypes;
|
||||
|
||||
/**
|
||||
* The types which will be accepted by the decoder. If a received message is an other type it will be just forwared
|
||||
* to the next {@link ChannelOutboundMessageHandler} in the {@link ChannelPipeline}
|
||||
*/
|
||||
protected MessageToMessageEncoder(Class<?>... acceptedMsgTypes) {
|
||||
this.acceptedMsgTypes = ChannelHandlerUtil.acceptedMessageTypes(acceptedMsgTypes);
|
||||
}
|
||||
@ -75,5 +101,15 @@ public abstract class MessageToMessageEncoder<I, O> extends ChannelOutboundMessa
|
||||
return ChannelHandlerUtil.acceptMessage(acceptedMsgTypes, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode from one message to an other. This method will be called till either the {@link MessageBuf} has nothing
|
||||
* left or till this method returns {@code null}.
|
||||
*
|
||||
* @param ctx the {@link ChannelHandlerContext} which this {@link MessageToMessageEncoder} belongs to
|
||||
* @param msg the message to encode to an other one
|
||||
* @return message the encoded message or {@code null} if more messages are needed be cause the implementation
|
||||
* needs to do some kind of aggragation
|
||||
* @throws Exception is thrown if an error accour
|
||||
*/
|
||||
public abstract O encode(ChannelHandlerContext ctx, I msg) throws Exception;
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
package io.netty.handler.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelHandlerUtil;
|
||||
@ -28,44 +27,41 @@ import io.netty.util.internal.Signal;
|
||||
* of a non-blocking decoder in the blocking I/O paradigm.
|
||||
* <p>
|
||||
* The biggest difference between {@link ReplayingDecoder} and
|
||||
* {@link FrameDecoder} is that {@link ReplayingDecoder} allows you to
|
||||
* {@link ByteToMessageDecoder} is that {@link ReplayingDecoder} allows you to
|
||||
* implement the {@code decode()} and {@code decodeLast()} methods just like
|
||||
* all required bytes were received already, rather than checking the
|
||||
* availability of the required bytes. For example, the following
|
||||
* {@link FrameDecoder} implementation:
|
||||
* {@link ByteToByteDecoder} implementation:
|
||||
* <pre>
|
||||
* public class IntegerHeaderFrameDecoder extends {@link FrameDecoder} {
|
||||
* public class IntegerHeaderFrameDecoder extends {@link ByteToMessageDecoder}<{@link ByteBuf}> {
|
||||
*
|
||||
* {@code @Override}
|
||||
* protected Object decode({@link ChannelHandlerContext} ctx,
|
||||
* {@link Channel} channel,
|
||||
* {@link ByteBuf} buf) throws Exception {
|
||||
* protected ByteBuf decode({@link ChannelHandlerContext} ctx,
|
||||
* {@link ByteBuf} in) throws Exception {
|
||||
*
|
||||
* if (buf.readableBytes() < 4) {
|
||||
* if (in.readableBytes() < 4) {
|
||||
* return <strong>null</strong>;
|
||||
* }
|
||||
*
|
||||
* buf.markReaderIndex();
|
||||
* int length = buf.readInt();
|
||||
* in.markReaderIndex();
|
||||
* int length = in.readInt();
|
||||
*
|
||||
* if (buf.readableBytes() < length) {
|
||||
* buf.resetReaderIndex();
|
||||
* if (in.readableBytes() < length) {
|
||||
* in.resetReaderIndex();
|
||||
* return <strong>null</strong>;
|
||||
* }
|
||||
*
|
||||
* return buf.readBytes(length);
|
||||
* return in.readBytes(length);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* is simplified like the following with {@link ReplayingDecoder}:
|
||||
* <pre>
|
||||
* public class IntegerHeaderFrameDecoder
|
||||
* extends {@link ReplayingDecoder}<{@link VoidEnum}> {
|
||||
* extends {@link ReplayingDecoder}<{@link ByteBuf},{@link Void}> {
|
||||
*
|
||||
* protected Object decode({@link ChannelHandlerContext} ctx,
|
||||
* {@link Channel} channel,
|
||||
* {@link ByteBuf} buf,
|
||||
* {@link VoidEnum} state) throws Exception {
|
||||
* {@link ByteBuf} buf) throws Exception {
|
||||
*
|
||||
* return buf.readBytes(buf.readInt());
|
||||
* }
|
||||
@ -104,12 +100,12 @@ import io.netty.util.internal.Signal;
|
||||
* <li>You must keep in mind that {@code decode(..)} method can be called many
|
||||
* times to decode a single message. For example, the following code will
|
||||
* not work:
|
||||
* <pre> public class MyDecoder extends {@link ReplayingDecoder}<{@link Void}> {
|
||||
* <pre> public class MyDecoder extends {@link ReplayingDecoder}<{@link Integer}, {@link Void}> {
|
||||
*
|
||||
* private final Queue<Integer> values = new LinkedList<Integer>();
|
||||
*
|
||||
* {@code @Override}
|
||||
* public Object decode(.., {@link ByteBuf} buffer, ..) throws Exception {
|
||||
* public {@link Integer} decode(.., {@link ByteBuf} in) throws Exception {
|
||||
*
|
||||
* // A message contains 2 integers.
|
||||
* values.offer(buffer.readInt());
|
||||
@ -124,12 +120,12 @@ import io.netty.util.internal.Signal;
|
||||
* The correct implementation looks like the following, and you can also
|
||||
* utilize the 'checkpoint' feature which is explained in detail in the
|
||||
* next section.
|
||||
* <pre> public class MyDecoder extends {@link ReplayingDecoder}<{@link Void}> {
|
||||
* <pre> public class MyDecoder extends {@link ReplayingDecoder}<{@link Integer}, {@link Void}> {
|
||||
*
|
||||
* private final Queue<Integer> values = new LinkedList<Integer>();
|
||||
*
|
||||
* {@code @Override}
|
||||
* public Object decode(.., {@link ByteBuf} buffer, ..) throws Exception {
|
||||
* public {@link Integer} decode(.., {@link ByteBuf} buffer) throws Exception {
|
||||
*
|
||||
* // Revert the state of the variable that might have been changed
|
||||
* // since the last partial decode.
|
||||
@ -171,7 +167,7 @@ import io.netty.util.internal.Signal;
|
||||
* }
|
||||
*
|
||||
* public class IntegerHeaderFrameDecoder
|
||||
* extends {@link ReplayingDecoder}<<strong>MyDecoderState</strong>> {
|
||||
* extends {@link ReplayingDecoder}<{@link ByteBuf}, <strong>MyDecoderState</strong>> {
|
||||
*
|
||||
* private int length;
|
||||
*
|
||||
@ -181,16 +177,14 @@ import io.netty.util.internal.Signal;
|
||||
* }
|
||||
*
|
||||
* {@code @Override}
|
||||
* protected Object decode({@link ChannelHandlerContext} ctx,
|
||||
* {@link Channel} channel,
|
||||
* {@link ByteBuf} buf,
|
||||
* <b>MyDecoderState</b> state) throws Exception {
|
||||
* switch (state) {
|
||||
* protected {@link ByteBuf} decode({@link ChannelHandlerContext} ctx,
|
||||
* {@link ByteBuf} in) throws Exception {
|
||||
* switch (state()) {
|
||||
* case READ_LENGTH:
|
||||
* length = buf.readInt();
|
||||
* <strong>checkpoint(MyDecoderState.READ_CONTENT);</strong>
|
||||
* case READ_CONTENT:
|
||||
* ChannelBuffer frame = buf.readBytes(length);
|
||||
* ByteBuf frame = buf.readBytes(length);
|
||||
* <strong>checkpoint(MyDecoderState.READ_LENGTH);</strong>
|
||||
* return frame;
|
||||
* default:
|
||||
@ -205,16 +199,14 @@ import io.netty.util.internal.Signal;
|
||||
* An alternative way to manage the decoder state is to manage it by yourself.
|
||||
* <pre>
|
||||
* public class IntegerHeaderFrameDecoder
|
||||
* extends {@link ReplayingDecoder}<<strong>{@link Void}</strong>> {
|
||||
* extends {@link ReplayingDecoder}<{@link ByteBuf},<strong>{@link Void}</strong>> {
|
||||
*
|
||||
* <strong>private boolean readLength;</strong>
|
||||
* private int length;
|
||||
*
|
||||
* {@code @Override}
|
||||
* protected Object decode({@link ChannelHandlerContext} ctx,
|
||||
* {@link Channel} channel,
|
||||
* {@link ByteBuf} buf,
|
||||
* {@link Void} state) throws Exception {
|
||||
* protected {@link ByteBuf} decode({@link ChannelHandlerContext} ctx,
|
||||
* {@link ByteBuf} in) throws Exception {
|
||||
* if (!readLength) {
|
||||
* length = buf.readInt();
|
||||
* <strong>readLength = true;</strong>
|
||||
@ -222,7 +214,7 @@ import io.netty.util.internal.Signal;
|
||||
* }
|
||||
*
|
||||
* if (readLength) {
|
||||
* ChannelBuffer frame = buf.readBytes(length);
|
||||
* ByteBuf frame = buf.readBytes(length);
|
||||
* <strong>readLength = false;</strong>
|
||||
* <strong>checkpoint();</strong>
|
||||
* return frame;
|
||||
@ -235,31 +227,26 @@ import io.netty.util.internal.Signal;
|
||||
* <p>
|
||||
* If you are going to write a protocol multiplexer, you will probably want to
|
||||
* replace a {@link ReplayingDecoder} (protocol detector) with another
|
||||
* {@link ReplayingDecoder} or {@link FrameDecoder} (actual protocol decoder).
|
||||
* {@link ReplayingDecoder}, {@link ByteToByteDecoder}, {@link ByteToMessageDecoder} or {@link MessageToMessageDecoder}
|
||||
* (actual protocol decoder).
|
||||
* It is not possible to achieve this simply by calling
|
||||
* {@link ChannelPipeline#replace(ChannelHandler, String, ChannelHandler)}, but
|
||||
* some additional steps are required:
|
||||
* <pre>
|
||||
* public class FirstDecoder extends {@link ReplayingDecoder}<{@link Void}> {
|
||||
*
|
||||
* public FirstDecoder() {
|
||||
* super(true); // Enable unfold
|
||||
* }
|
||||
* public class FirstDecoder extends {@link ReplayingDecoder}<{@link Object}, {@link Void}> {
|
||||
*
|
||||
* {@code @Override}
|
||||
* protected Object decode({@link ChannelHandlerContext} ctx,
|
||||
* {@link Channel} ch,
|
||||
* {@link ByteBuf} buf,
|
||||
* {@link Void} state) {
|
||||
* {@link ByteBuf} in) {
|
||||
* ...
|
||||
* // Decode the first message
|
||||
* Object firstMessage = ...;
|
||||
*
|
||||
* // Add the second decoder
|
||||
* ctx.getPipeline().addLast("second", new SecondDecoder());
|
||||
* ctx.pipeline().addLast("second", new SecondDecoder());
|
||||
*
|
||||
* // Remove the first decoder (me)
|
||||
* ctx.getPipeline().remove(this);
|
||||
* ctx.pipeline().remove(this);
|
||||
*
|
||||
* if (buf.readable()) {
|
||||
* // Hand off the remaining data to the second decoder
|
||||
|
@ -31,6 +31,9 @@ import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Special {@link ByteBuf} implementation which is used by the {@link ReplayingDecoder}
|
||||
*/
|
||||
final class ReplayingDecoderBuffer implements ByteBuf {
|
||||
|
||||
private static final Signal REPLAY = ReplayingDecoder.REPLAY;
|
||||
|
@ -16,8 +16,8 @@
|
||||
package io.netty.handler.codec;
|
||||
|
||||
/**
|
||||
* An {@link Exception} which is thrown when the length of the frame
|
||||
* decoded by {@link DelimiterBasedFrameDecoder} is greater than the maximum.
|
||||
* An {@link DecoderException} which is thrown when the length of the frame
|
||||
* decoded is greater than the allowed maximum.
|
||||
*
|
||||
* @apiviz.exclude
|
||||
*/
|
||||
|
@ -15,11 +15,9 @@
|
||||
*/
|
||||
package io.netty.handler.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
/**
|
||||
* An {@link Exception} which is thrown when a user calls an unsupported
|
||||
* operation on a {@link ByteBuf} in a {@link ReplayingDecoder}
|
||||
* An {@link UnsupportedOperationException} which is thrown when a user calls an unsupported
|
||||
* operation on a {@link ReplayingDecoderBuffer} in a {@link ReplayingDecoder}
|
||||
* implementation.
|
||||
*/
|
||||
public class UnreplayableOperationException extends UnsupportedOperationException {
|
||||
|
@ -15,6 +15,9 @@
|
||||
*/
|
||||
package io.netty.handler.codec;
|
||||
|
||||
/**
|
||||
* Thrown if an unsupported message is received by an codec.
|
||||
*/
|
||||
public class UnsupportedMessageTypeException extends CodecException {
|
||||
|
||||
private static final long serialVersionUID = 2799598826487038726L;
|
||||
|
@ -28,9 +28,7 @@ import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
* A {@link ChannelHandler} that logs all events via {@link InternalLogger}.
|
||||
* By default, all events are logged at <tt>DEBUG</tt> level. You can extend
|
||||
* this class and override {@link #log(ChannelEvent)} to change the default
|
||||
* behavior.
|
||||
* By default, all events are logged at <tt>DEBUG</tt> level.
|
||||
* @apiviz.landmark
|
||||
*/
|
||||
@Sharable
|
||||
@ -118,7 +116,6 @@ public class LoggingHandler extends ChannelHandlerAdapter {
|
||||
|
||||
/**
|
||||
* Returns the {@link InternalLogLevel} that this handler uses to log
|
||||
* a {@link ChannelEvent}.
|
||||
*/
|
||||
public LogLevel level() {
|
||||
return level;
|
||||
|
Loading…
Reference in New Issue
Block a user