package org.jboss.netty.channel;
import java.net.SocketAddress;
import java.util.Map;
import org.jboss.netty.util.internal.ConversionUtil;
public final class Channels {
// pipeline factory methods
/**
* ����һ��Ĭ�ϵ�ChannelPipeline.
*/
public static ChannelPipeline pipeline() {
return new DefaultChannelPipeline();
}
/**
* Creates a new {@link ChannelPipeline} which contains the specified
* {@link ChannelHandler}s. The names of the specified handlers are
* generated automatically; the first handler's name is {@code "0"}, the
* second handler's name is {@code "1"}, the third handler's name is
* {@code "2"}, and so on.
*/
public static ChannelPipeline pipeline(ChannelHandler... handlers) {
if (handlers == null) {
throw new NullPointerException("handlers");
}
ChannelPipeline newPipeline = pipeline();
for (int i = 0; i < handlers.length; i++) {
ChannelHandler h = handlers[i];
if (h == null) {
break;
}
newPipeline.addLast(ConversionUtil.toString(i), h);
}
return newPipeline;
}
/**
* Creates a new ChannelPipeline which contains the same entries
* with the specified pipeline. Please note that only the names and
* the references of the ChannelHandlers will be copied; a new
* ChannelHandler instance will never be created.
* ����һ���µ�ChannelPipeline��Ҫ������ָ����pipeline������ͬ������
* ֻ��pipeline�����ֺ�Handler�����ûḴ�ƣ������ᴴ���µ�Handlerʵ��
*/
public static ChannelPipeline pipeline(ChannelPipeline pipeline) {
ChannelPipeline newPipeline = pipeline();
for (Map.Entry<String, ChannelHandler> e : pipeline.toMap().entrySet()) {
newPipeline.addLast(e.getKey(), e.getValue());
}
return newPipeline;
}
// ����һ��������������pipeline�����������������ͬ��������
public static ChannelPipelineFactory pipelineFactory(
final ChannelPipeline pipeline) {
return new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return pipeline(pipeline);
}
};
}
// future��������
//Ϊָ����Channel����һ������ȡ���ģ�non-cancellable��hannelFuturefor
public static ChannelFuture future(Channel channel) {
return future(channel, false);
}
//������ȡ������˼�ǣ����ص�Future���Ե�����cancel()������ȡ�������Future������IO����
public static ChannelFuture future(Channel channel, boolean cancellable) {
return new DefaultChannelFuture(channel, cancellable);
}
/**
* Creates a new {@link ChannelFuture} which is already succeeded for the
* specified {@link Channel}.
*/
public static ChannelFuture succeededFuture(Channel channel) {
if (channel instanceof AbstractChannel) {
return ((AbstractChannel) channel).getSucceededFuture();
} else {
return new SucceededChannelFuture(channel);
}
}
/**
* Creates a new {@link ChannelFuture} which has failed already for the
* specified {@link Channel}.
*
* @param cause
* the cause of the failure
*/
public static ChannelFuture failedFuture(Channel channel, Throwable cause) {
return new FailedChannelFuture(channel, cause);
}
// event emission methods �¼����䷽��
//����"channelOpen"�¼�����ͨ������ˮ���е�һ��ChannelUpstreamHandler
//������Channel��parent����ôһ��"childChannelOpen"�¼�Ҳ�ᷢ��
public static void fireChannelOpen(Channel channel) {
// Notify the parent handler.
if (channel.getParent() != null) {
fireChildChannelStateChanged(channel.getParent(), channel);
}
channel.getPipeline().sendUpstream(
new UpstreamChannelStateEvent(channel, ChannelState.OPEN,
Boolean.TRUE));
}
/**
* Sends a {@code "channelOpen"} event to the {@link ChannelUpstreamHandler}
* which is placed in the closest upstream from the handler associated with
* the specified {@link ChannelHandlerContext}.
* <p>
* Please note that this method does not trigger a
* {@code "childChannelOpen"} event unlike {@link #fireChannelOpen(Channel)}
* method.
*/
public static void fireChannelOpen(ChannelHandlerContext ctx) {
ctx.sendUpstream(new UpstreamChannelStateEvent(ctx.getChannel(),
ChannelState.OPEN, Boolean.TRUE));
}
/**
* ����һ��ChannelUpstreamHandler����һ��"channelBound"��״̬�¼�
* �����������ְɹ�
*/
public static void fireChannelBound(Channel channel,
SocketAddress localAddress) {
channel.getPipeline().sendUpstream(
new UpstreamChannelStateEvent(channel, ChannelState.BOUND,
localAddress));
}
/**
* Sends a {@code "channelBound"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param localAddress
* the local address where the specified channel is bound
*/
public static void fireChannelBound(ChannelHandlerContext ctx,
SocketAddress localAddress) {
ctx.sendUpstream(new UpstreamChannelStateEvent(ctx.getChannel(),
ChannelState.BOUND, localAddress));
}
/**
* Sends a {@code "channelConnected"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*
* @param remoteAddress
* the remote address where the specified channel is connected
*/
public static void fireChannelConnected(Channel channel,
SocketAddress remoteAddress) {
channel.getPipeline().sendUpstream(
new UpstreamChannelStateEvent(channel, ChannelState.CONNECTED,
remoteAddress));
}
/**
* Sends a {@code "channelConnected"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param remoteAddress
* the remote address where the specified channel is connected
*/
public static void fireChannelConnected(ChannelHandlerContext ctx,
SocketAddress remoteAddress) {
ctx.sendUpstream(new UpstreamChannelStateEvent(ctx.getChannel(),
ChannelState.CONNECTED, remoteAddress));
}
/**
* Sends a {@code "messageReceived"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*
* @param message
* the received message
*/
public static void fireMessageReceived(Channel channel, Object message) {
fireMessageReceived(channel, message, null);
}
/**
* Sends a {@code "messageReceived"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel} belongs.
*
* @param message
* the received message
* @param remoteAddress
* the remote address where the received message came from
*/
public static void fireMessageReceived(Channel channel, Object message,
SocketAddress remoteAddress) {
channel.getPipeline().sendUpstream(
new UpstreamMessageEvent(channel, message, remoteAddress));
}
/**
* Sends a {@code "messageReceived"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param message
* the received message
*/
public static void fireMessageReceived(ChannelHandlerContext ctx,
Object message) {
ctx.sendUpstream(new UpstreamMessageEvent(ctx.getChannel(), message,
null));
}
/**
* Sends a {@code "messageReceived"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param message
* the received message
* @param remoteAddress
* the remote address where the received message came from
*/
public static void fireMessageReceived(ChannelHandlerContext ctx,
Object message, SocketAddress remoteAddress) {
ctx.sendUpstream(new UpstreamMessageEvent(ctx.getChannel(), message,
remoteAddress));
}
/**
* Sends a {@code "writeComplete"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel} in the next io-thread.
*/
public static ChannelFuture fireWriteCompleteLater(final Channel channel,
final long amount) {
return channel.getPipeline().execute(new Runnable() {
public void run() {
fireWriteComplete(channel, amount);
}
});
}
/**
* Sends a {@code "writeComplete"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*/
public static void fireWriteComplete(Channel channel, long amount) {
if (amount == 0) {
return;
}
channel.getPipeline().sendUpstream(
new DefaultWriteCompletionEvent(channel, amount));
}
/**
* Sends a {@code "writeComplete"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*/
public static void fireWriteComplete(ChannelHandlerContext ctx, long amount) {
ctx.sendUpstream(new DefaultWriteCompletionEvent(ctx.getChannel(),
amount));
}
/**
* Sends a {@code "channelInterestChanged"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel} once the io-thread runs again.
*/
public static ChannelFuture fireChannelInterestChangedLater(
final Channel channel) {
return channel.getPipeline().execute(new Runnable() {
public void run() {
fireChannelInterestChanged(channel);
}
});
}
/**
* Sends a {@code "channelInterestChanged"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*/
public static void fireChannelInterestChanged(Channel channel) {
channel.getPipeline().sendUpstream(
new UpstreamChannelStateEvent(channel,
ChannelState.INTEREST_OPS, Channel.OP_READ));
}
/**
* Sends a {@code "channelInterestChanged"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*/
public static void fireChannelInterestChanged(ChannelHandlerContext ctx) {
ctx.sendUpstream(new UpstreamChannelStateEvent(ctx.getChannel(),
ChannelState.INTEREST_OPS, Channel.OP_READ));
}
/**
* Sends a {@code "channelDisconnected"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel} once the io-thread runs again.
*/
public static ChannelFuture fireChannelDisconnectedLater(
final Channel channel) {
return channel.getPipeline().execute(new Runnable() {
public void run() {
fireChannelDisconnected(channel);
}
});
}
/**
* Sends a {@code "channelDisconnected"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*/
public static void fireChannelDisconnected(Channel channel) {
channel.getPipeline().sendUpstream(
new UpstreamChannelStateEvent(channel, ChannelState.CONNECTED,
null));
}
/**
* Sends a {@code "channelDisconnected"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*/
public static void fireChannelDisconnected(ChannelHandlerContext ctx) {
ctx.sendUpstream(new UpstreamChannelStateEvent(ctx.getChannel(),
ChannelState.CONNECTED, null));
}
/**
* Sends a {@code "channelUnbound"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel} once the io-thread runs again.
*/
public static ChannelFuture fireChannelUnboundLater(final Channel channel) {
return channel.getPipeline().execute(new Runnable() {
public void run() {
fireChannelUnbound(channel);
}
});
}
/**
* Sends a {@code "channelUnbound"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*/
public static void fireChannelUnbound(Channel channel) {
channel.getPipeline()
.sendUpstream(
new UpstreamChannelStateEvent(channel,
ChannelState.BOUND, null));
}
/**
* Sends a {@code "channelUnbound"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*/
public static void fireChannelUnbound(ChannelHandlerContext ctx) {
ctx.sendUpstream(new UpstreamChannelStateEvent(ctx.getChannel(),
ChannelState.BOUND, null));
}
/**
* Sends a {@code "channelClosed"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel} once the io-thread runs again.
*/
public static ChannelFuture fireChannelClosedLater(final Channel channel) {
return channel.getPipeline().execute(new Runnable() {
public void run() {
fireChannelClosed(channel);
}
});
}
/**
* Sends a {@code "channelClosed"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*/
public static void fireChannelClosed(Channel channel) {
channel.getPipeline().sendUpstream(
new UpstreamChannelStateEvent(channel, ChannelState.OPEN,
Boolean.FALSE));
// Notify the parent handler.
if (channel.getParent() != null) {
fireChildChannelStateChanged(channel.getParent(), channel);
}
}
/**
* Sends a {@code "channelClosed"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*/
public static void fireChannelClosed(ChannelHandlerContext ctx) {
ctx.sendUpstream(new UpstreamChannelStateEvent(ctx.getChannel(),
ChannelState.OPEN, Boolean.FALSE));
}
/**
* Sends a {@code "exceptionCaught"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel} once the io-thread runs again.
*/
public static ChannelFuture fireExceptionCaughtLater(final Channel channel,
final Throwable cause) {
return channel.getPipeline().execute(new Runnable() {
public void run() {
fireExceptionCaught(channel, cause);
}
});
}
/**
* Sends a {@code "exceptionCaught"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext} once the io-thread runs again.
*/
public static ChannelFuture fireExceptionCaughtLater(
final ChannelHandlerContext ctx, final Throwable cause) {
return ctx.getPipeline().execute(new Runnable() {
public void run() {
fireExceptionCaught(ctx, cause);
}
});
}
/**
* Sends a {@code "exceptionCaught"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*/
public static void fireExceptionCaught(Channel channel, Throwable cause) {
channel.getPipeline().sendUpstream(
new DefaultExceptionEvent(channel, cause));
}
/**
* Sends a {@code "exceptionCaught"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*/
public static void fireExceptionCaught(ChannelHandlerContext ctx,
Throwable cause) {
ctx.sendUpstream(new DefaultExceptionEvent(ctx.getChannel(), cause));
}
private static void fireChildChannelStateChanged(Channel channel,
Channel childChannel) {
channel.getPipeline().sendUpstream(
new DefaultChildChannelStateEvent(channel, childChannel));
}
// ���ͨ������ˮ�ߵ����һ��handler����һ��bind����
public static ChannelFuture bind(Channel channel, SocketAddress localAddress) {
if (localAddress == null) {
throw new NullPointerException("localAddress");
}
//����һ������ȡ����ChannelFuture
ChannelFuture future = future(channel);
//Ӧ���Ƿ�������ʵ�ֲ�������ChannelSink��״̬ʱBOUND��ֵ��LocalAddress
channel.getPipeline().sendDownstream(
new DownstreamChannelStateEvent(channel, future,
ChannelState.BOUND, localAddress));
return future;
}
/**
* Sends a {@code "bind"} request to the {@link ChannelDownstreamHandler}
* which is placed in the closest downstream from the handler associated
* with the specified {@link ChannelHandlerContext}.
*
* @param ctx
* the context
* @param future
* the future which will be notified when the bind operation is
* done
* @param localAddress
* the local address to bind to
*/
public static void bind(ChannelHandlerContext ctx, ChannelFuture future,
SocketAddress localAddress) {
if (localAddress == null) {
throw new NullPointerException("localAddress");
}
ctx.sendDownstream(new DownstreamChannelStateEvent(ctx.getChannel(),
future, ChannelState.BOUND, localAddress));
}
/**
* Sends a {@code "unbind"} request to the {@link ChannelDownstreamHandler}
* which is placed in the closest downstream from the handler associated
* with the specified {@link ChannelHandlerContext}.
*
* @param ctx
* the context
* @param future
* the future which will be notified when the unbind operation is
* done
*/
public static void unbind(ChannelHandlerContext ctx, ChannelFuture future) {
ctx.sendDownstream(new DownstreamChannelStateEvent(ctx.getChannel(),
future, ChannelState.BOUND, null));
}
/**
* Sends a {@code "unbind"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*
* @param channel
* the channel to unbind
*
* @return the {@link ChannelFuture} which will be notified when the unbind
* operation is done
*/
public static ChannelFuture unbind(Channel channel) {
ChannelFuture future = future(channel);
channel.getPipeline().sendDownstream(
new DownstreamChannelStateEvent(channel, future,
ChannelState.BOUND, null));
return future;
}
/**
* Sends a {@code "connect"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*
* @param channel
* the channel to attempt a connection
* @param remoteAddress
* the remote address to connect to
*
* @return the {@link ChannelFuture} which will be notified when the
* connection attempt is done
*/
public static ChannelFuture connect(Channel channel,
SocketAddress remoteAddress) {
if (remoteAddress == null) {
throw new NullPointerException("remoteAddress");
}
ChannelFuture future = future(channel, true);
channel.getPipeline().sendDownstream(
new DownstreamChannelStateEvent(channel, future,
ChannelState.CONNECTED, remoteAddress));
return future;
}
/**
* Sends a {@code "connect"} request to the {@link ChannelDownstreamHandler}
* which is placed in the closest downstream from the handler associated
* with the specified {@link ChannelHandlerContext}.
*
* @param ctx
* the context
* @param future
* the future which will be notified when the connection attempt
* is done
* @param remoteAddress
* the remote address to connect to
*/
public static void connect(ChannelHandlerContext ctx, ChannelFuture future,
SocketAddress remoteAddress) {
if (remoteAddress == null) {
throw new NullPointerException("remoteAddress");
}
ctx.sendDownstream(new DownstreamChannelStateEvent(ctx.getChannel(),
future, ChannelState.CONNECTED, remoteAddress));
}
/**
* Sends a {@code "write"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*
* @param channel
* the channel to write a message
* @param message
* the message to write to the channel
*
* @return the {@link ChannelFuture} which will be notified when the write
* operation is done
*/
public static ChannelFuture write(Channel channel, Object message) {
return write(channel, message, null);
}
/**
* Sends a {@code "write"} request to the {@link ChannelDownstreamHandler}
* which is placed in the closest downstream from the handler associated
* with the specified {@link ChannelHandlerContext}.
*
* @param ctx
* the context
* @param future
* the future which will be notified when the write operation is
* done
*/
public static void write(ChannelHandlerContext ctx, ChannelFuture future,
Object message) {
write(ctx, future, message, null);
}
/**
* Sends a {@code "write"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*
* @param channel
* the channel to write a message
* @param message
* the message to write to the channel
* @param remoteAddress
* the destination of the message. {@code null} to use the
* default remote address
*
* @return the {@link ChannelFuture} which will be notified when the write
* operation is done
*/
public static ChannelFuture write(Channel channel, Object message,
SocketAddress remoteAddress) {
ChannelFuture future = future(channel);
channel.getPipeline().sendDownstream(
new DownstreamMessageEvent(channel, future, message,
remoteAddress));
return future;
}
/**
* Sends a {@code "write"} request to the {@link ChannelDownstreamHandler}
* which is placed in the closest downstream from the handler associated
* with the specified {@link ChannelHandlerContext}.
*
* @param ctx
* the context
* @param future
* the future which will be notified when the write operation is
* done
* @param message
* the message to write to the channel
* @param remoteAddress
* the destination of the message. {@code null} to use the
* default remote address.
*/
public static void write(ChannelHandlerContext ctx, ChannelFuture future,
Object message, SocketAddress remoteAddress) {
ctx.sendDownstream(new DownstreamMessageEvent(ctx.getChannel(), future,
message, remoteAddress));
}
/**
* Sends a {@code "setInterestOps"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*
* @param channel
* the channel to change its interestOps
* @param interestOps
* the new interestOps
*
* @return the {@link ChannelFuture} which will be notified when the
* interestOps is changed
*/
public static ChannelFuture setInterestOps(Channel channel, int interestOps) {
validateInterestOps(interestOps);
interestOps = filterDownstreamInterestOps(interestOps);
ChannelFuture future = future(channel);
channel.getPipeline().sendDownstream(
new DownstreamChannelStateEvent(channel, future,
ChannelState.INTEREST_OPS, interestOps));
return future;
}
/**
* Sends a {@code "setInterestOps"} request to the
* {@link ChannelDownstreamHandler} which is placed in the closest
* downstream from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param ctx
* the context
* @param future
* the future which will be notified when the interestOps is
* changed.
*/
public static void setInterestOps(ChannelHandlerContext ctx,
ChannelFuture future, int interestOps) {
validateInterestOps(interestOps);
interestOps = filterDownstreamInterestOps(interestOps);
ctx.sendDownstream(new DownstreamChannelStateEvent(ctx.getChannel(),
future, ChannelState.INTEREST_OPS, interestOps));
}
/**
* Sends a {@code "disconnect"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of the
* specified {@link Channel}.
*
* @param channel
* the channel to disconnect
*
* @return the {@link ChannelFuture} which will be notified on disconnection
*/
public static ChannelFuture disconnect(Channel channel) {
ChannelFuture future = future(channel);
channel.getPipeline().sendDownstream(
new DownstreamChannelStateEvent(channel, future,
ChannelState.CONNECTED, null));
return future;
}
/**
* Sends a {@code "disconnect"} request to the
* {@link ChannelDownstreamHandler} which is placed in the closest
* downstream from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param ctx
* the context
* @param future
* the future which will be notified on disconnection
*/
public static void disconnect(ChannelHandlerContext ctx,
ChannelFuture future) {
ctx.sendDownstream(new DownstreamChannelStateEvent(ctx.getChannel(),
future, ChannelState.CONNECTED, null));
}
// ���ͨ������ˮ�ߵ����һ��handler����һ��bind����
public static ChannelFuture close(Channel channel) {
ChannelFuture future = channel.getCloseFuture();
channel.getPipeline().sendDownstream(
new DownstreamChannelStateEvent(channel, future,
ChannelState.OPEN, Boolean.FALSE));
return future;
}
/**
* Sends a {@code "close"} request to the {@link ChannelDownstreamHandler}
* which is placed in the closest downstream from the handler associated
* with the specified {@link ChannelHandlerContext}.
*
* @param ctx
* the context
* @param future
* the future which will be notified on closure
*/
public static void close(ChannelHandlerContext ctx, ChannelFuture future) {
ctx.sendDownstream(new DownstreamChannelStateEvent(ctx.getChannel(),
future, ChannelState.OPEN, Boolean.FALSE));
}
private static void validateInterestOps(int interestOps) {
switch (interestOps) {
case Channel.OP_NONE:
case Channel.OP_READ:
case Channel.OP_WRITE:
case Channel.OP_READ_WRITE:
break;
default:
throw new IllegalArgumentException("Invalid interestOps: "
+ interestOps);
}
}
private static int filterDownstreamInterestOps(int interestOps) {
return interestOps & ~Channel.OP_WRITE;
}
private Channels() {
// Unused
}
}