/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import io.netty.util.AttributeMap;
import io.netty.util.concurrent.EventExecutor;
import java.nio.channels.Channels;
Enables a ChannelHandler
to interact with its ChannelPipeline
and other handlers. Among other things a handler can notify the next ChannelHandler
in the ChannelPipeline
as well as modify the ChannelPipeline
it belongs to dynamically. Notify
You can notify the closest handler in the same ChannelPipeline
by calling one of the various methods provided here. Please refer to ChannelPipeline
to understand how an event flows. Modifying a pipeline
You can get the ChannelPipeline
your handler belongs to by calling pipeline()
. A non-trivial application could insert, remove, or replace handlers in the pipeline dynamically at runtime. Retrieving for later use
You can keep the ChannelHandlerContext
for later use, such as triggering an event outside the handler methods, even from a different thread. public class MyHandler extends ChannelDuplexHandler
{ private ChannelHandlerContext
ctx; public void beforeAdd(ChannelHandlerContext
ctx) { this.ctx = ctx;
}
public void login(String username, password) {
ctx.write(new LoginMessage(username, password));
}
...
}
Storing stateful information
attr(AttributeKey<Object>)
allow you to store and access stateful information that is related with a handler and its context. Please refer to ChannelHandler
to learn various recommended ways to manage stateful information. A handler can have more than one context
Please note that a ChannelHandler
instance can be added to more than one ChannelPipeline
. It means a single ChannelHandler
instance can have more than one ChannelHandlerContext
and therefore the single instance can be invoked with different ChannelHandlerContext
s if it is added to one or more ChannelPipeline
s more than once. For example, the following handler will have as many independent AttributeKey
s as how many times it is added to pipelines, regardless if it is added to the same pipeline multiple times or added to different pipelines multiple times:
public class FactorialHandler extends ChannelInboundHandlerAdapter
{ private final AttributeKey
<Integer
> counter = AttributeKey
.valueOf("counter"); // This handler will receive a sequence of increasing integers starting // from 1. @Override
public void channelRead(ChannelHandlerContext
ctx, Object msg) { Integer a = ctx.attr(counter).get(); if (a == null) { a = 1; } attr.set(a * (Integer) msg); } } // Different context objects are given to "f1", "f2", "f3", and "f4" even if // they refer to the same handler instance. Because the FactorialHandler // stores its state in a context object (using an AttributeKey
), the factorial is // calculated correctly 4 times once the two pipelines (p1 and p2) are active. FactorialHandler fh = new FactorialHandler(); ChannelPipeline
p1 = Channels
.pipeline(); p1.addLast("f1", fh); p1.addLast("f2", fh); ChannelPipeline
p2 = Channels
.pipeline(); p2.addLast("f3", fh); p2.addLast("f4", fh);
Additional resources worth reading
Please refer to the ChannelHandler
, and ChannelPipeline
to find out more about inbound and outbound operations, what fundamental differences they have, how they flow in a pipeline, and how to handle the operation in your application.
/**
* Enables a {@link ChannelHandler} to interact with its {@link ChannelPipeline}
* and other handlers. Among other things a handler can notify the next {@link ChannelHandler} in the
* {@link ChannelPipeline} as well as modify the {@link ChannelPipeline} it belongs to dynamically.
*
* <h3>Notify</h3>
*
* You can notify the closest handler in the same {@link ChannelPipeline} by calling one of the various methods
* provided here.
*
* Please refer to {@link ChannelPipeline} to understand how an event flows.
*
* <h3>Modifying a pipeline</h3>
*
* You can get the {@link ChannelPipeline} your handler belongs to by calling
* {@link #pipeline()}. A non-trivial application could insert, remove, or
* replace handlers in the pipeline dynamically at runtime.
*
* <h3>Retrieving for later use</h3>
*
* You can keep the {@link ChannelHandlerContext} for later use, such as
* triggering an event outside the handler methods, even from a different thread.
* <pre>
* public class MyHandler extends {@link ChannelDuplexHandler} {
*
* <b>private {@link ChannelHandlerContext} ctx;</b>
*
* public void beforeAdd({@link ChannelHandlerContext} ctx) {
* <b>this.ctx = ctx;</b>
* }
*
* public void login(String username, password) {
* ctx.write(new LoginMessage(username, password));
* }
* ...
* }
* </pre>
*
* <h3>Storing stateful information</h3>
*
* {@link #attr(AttributeKey)} allow you to
* store and access stateful information that is related with a handler and its
* context. Please refer to {@link ChannelHandler} to learn various recommended
* ways to manage stateful information.
*
* <h3>A handler can have more than one context</h3>
*
* Please note that a {@link ChannelHandler} instance can be added to more than
* one {@link ChannelPipeline}. It means a single {@link ChannelHandler}
* instance can have more than one {@link ChannelHandlerContext} and therefore
* the single instance can be invoked with different
* {@link ChannelHandlerContext}s if it is added to one or more
* {@link ChannelPipeline}s more than once.
* <p>
* For example, the following handler will have as many independent {@link AttributeKey}s
* as how many times it is added to pipelines, regardless if it is added to the
* same pipeline multiple times or added to different pipelines multiple times:
* <pre>
* public class FactorialHandler extends {@link ChannelInboundHandlerAdapter} {
*
* private final {@link AttributeKey}<{@link Integer}> counter = {@link AttributeKey}.valueOf("counter");
*
* // This handler will receive a sequence of increasing integers starting
* // from 1.
* {@code @Override}
* public void channelRead({@link ChannelHandlerContext} ctx, Object msg) {
* Integer a = ctx.attr(counter).get();
*
* if (a == null) {
* a = 1;
* }
*
* attr.set(a * (Integer) msg);
* }
* }
*
* // Different context objects are given to "f1", "f2", "f3", and "f4" even if
* // they refer to the same handler instance. Because the FactorialHandler
* // stores its state in a context object (using an {@link AttributeKey}), the factorial is
* // calculated correctly 4 times once the two pipelines (p1 and p2) are active.
* FactorialHandler fh = new FactorialHandler();
*
* {@link ChannelPipeline} p1 = {@link Channels}.pipeline();
* p1.addLast("f1", fh);
* p1.addLast("f2", fh);
*
* {@link ChannelPipeline} p2 = {@link Channels}.pipeline();
* p2.addLast("f3", fh);
* p2.addLast("f4", fh);
* </pre>
*
* <h3>Additional resources worth reading</h3>
* <p>
* Please refer to the {@link ChannelHandler}, and
* {@link ChannelPipeline} to find out more about inbound and outbound operations,
* what fundamental differences they have, how they flow in a pipeline, and how to handle
* the operation in your application.
*/
public interface ChannelHandlerContext extends AttributeMap, ChannelInboundInvoker, ChannelOutboundInvoker {
Return the Channel
which is bound to the ChannelHandlerContext
. /**
* Return the {@link Channel} which is bound to the {@link ChannelHandlerContext}.
*/
Channel channel();
Returns the EventExecutor
which is used to execute an arbitrary task. /**
* Returns the {@link EventExecutor} which is used to execute an arbitrary task.
*/
EventExecutor executor();
The unique name of the ChannelHandlerContext
.The name was used when then ChannelHandler
was added to the ChannelPipeline
. This name can also be used to access the registered ChannelHandler
from the ChannelPipeline
. /**
* The unique name of the {@link ChannelHandlerContext}.The name was used when then {@link ChannelHandler}
* was added to the {@link ChannelPipeline}. This name can also be used to access the registered
* {@link ChannelHandler} from the {@link ChannelPipeline}.
*/
String name();
The ChannelHandler
that is bound this ChannelHandlerContext
. /**
* The {@link ChannelHandler} that is bound this {@link ChannelHandlerContext}.
*/
ChannelHandler handler();
Return true
if the ChannelHandler
which belongs to this context was removed from the ChannelPipeline
. Note that this method is only meant to be called from with in the EventLoop
. /**
* Return {@code true} if the {@link ChannelHandler} which belongs to this context was removed
* from the {@link ChannelPipeline}. Note that this method is only meant to be called from with in the
* {@link EventLoop}.
*/
boolean isRemoved();
@Override
ChannelHandlerContext fireChannelRegistered();
@Override
ChannelHandlerContext fireChannelUnregistered();
@Override
ChannelHandlerContext fireChannelActive();
@Override
ChannelHandlerContext fireChannelInactive();
@Override
ChannelHandlerContext fireExceptionCaught(Throwable cause);
@Override
ChannelHandlerContext fireUserEventTriggered(Object evt);
@Override
ChannelHandlerContext fireChannelRead(Object msg);
@Override
ChannelHandlerContext fireChannelReadComplete();
@Override
ChannelHandlerContext fireChannelWritabilityChanged();
@Override
ChannelHandlerContext read();
@Override
ChannelHandlerContext flush();
Return the assigned ChannelPipeline
/**
* Return the assigned {@link ChannelPipeline}
*/
ChannelPipeline pipeline();
Return the assigned ByteBufAllocator
which will be used to allocate ByteBuf
s. /**
* Return the assigned {@link ByteBufAllocator} which will be used to allocate {@link ByteBuf}s.
*/
ByteBufAllocator alloc();
Deprecated: Use AttributeMap.attr(AttributeKey<Object>)
/**
* @deprecated Use {@link Channel#attr(AttributeKey)}
*/
@Deprecated
@Override
<T> Attribute<T> attr(AttributeKey<T> key);
Deprecated: Use AttributeMap.hasAttr(AttributeKey<Object>)
/**
* @deprecated Use {@link Channel#hasAttr(AttributeKey)}
*/
@Deprecated
@Override
<T> boolean hasAttr(AttributeKey<T> key);
}