Allow to extend IdleStateHandler and so provide more details for IdleStateEvents

Motivation:

Sometimes it is useful to include more details in the IdleStateEvents that are produced by the IdleStateHandler. For this users should be able to create their own IdleStateEvents that encapsulate more informations.

Modifications:

- Make IdleStateEvent constructor protected and the class non-final
- Add protected method to IdleStateHandler that users can override and so create their own IdleStateEvents.

Result:

More flexible and customizable IdleStateEvents / IdleStateHandler
This commit is contained in:
Norman Maurer 2016-05-09 10:18:10 +02:00
parent 1f8e192e21
commit 89eae94542
2 changed files with 32 additions and 15 deletions

View File

@ -16,11 +16,12 @@
package io.netty.handler.timeout; package io.netty.handler.timeout;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.util.internal.ObjectUtil;
/** /**
* A user event triggered by {@link IdleStateHandler} when a {@link Channel} is idle. * A user event triggered by {@link IdleStateHandler} when a {@link Channel} is idle.
*/ */
public final class IdleStateEvent { public class IdleStateEvent {
public static final IdleStateEvent FIRST_READER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.READER_IDLE, true); public static final IdleStateEvent FIRST_READER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.READER_IDLE, true);
public static final IdleStateEvent READER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.READER_IDLE, false); public static final IdleStateEvent READER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.READER_IDLE, false);
public static final IdleStateEvent FIRST_WRITER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.WRITER_IDLE, true); public static final IdleStateEvent FIRST_WRITER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.WRITER_IDLE, true);
@ -31,8 +32,14 @@ public final class IdleStateEvent {
private final IdleState state; private final IdleState state;
private final boolean first; private final boolean first;
private IdleStateEvent(IdleState state, boolean first) { /**
this.state = state; * Constructor for sub-classes.
*
* @param state the {@link IdleStateEvent} which triggered the event.
* @param first {@code true} if its the first idle event for the {@link IdleStateEvent}.
*/
protected IdleStateEvent(IdleState state, boolean first) {
this.state = ObjectUtil.checkNotNull(state, "state");
this.first = first; this.first = first;
} }

View File

@ -343,6 +343,22 @@ public class IdleStateHandler extends ChannelDuplexHandler {
ctx.fireUserEventTriggered(evt); ctx.fireUserEventTriggered(evt);
} }
/**
* Returns a {@link IdleStateEvent}.
*/
protected IdleStateEvent newIdleStateEvent(IdleState state, boolean first) {
switch (state) {
case ALL_IDLE:
return first ? IdleStateEvent.FIRST_ALL_IDLE_STATE_EVENT : IdleStateEvent.ALL_IDLE_STATE_EVENT;
case READER_IDLE:
return first ? IdleStateEvent.FIRST_READER_IDLE_STATE_EVENT : IdleStateEvent.READER_IDLE_STATE_EVENT;
case WRITER_IDLE:
return first ? IdleStateEvent.FIRST_WRITER_IDLE_STATE_EVENT : IdleStateEvent.WRITER_IDLE_STATE_EVENT;
default:
throw new Error();
}
}
private final class ReaderIdleTimeoutTask implements Runnable { private final class ReaderIdleTimeoutTask implements Runnable {
private final ChannelHandlerContext ctx; private final ChannelHandlerContext ctx;
@ -367,13 +383,11 @@ public class IdleStateHandler extends ChannelDuplexHandler {
readerIdleTimeout = readerIdleTimeout =
ctx.executor().schedule(this, readerIdleTimeNanos, TimeUnit.NANOSECONDS); ctx.executor().schedule(this, readerIdleTimeNanos, TimeUnit.NANOSECONDS);
try { try {
IdleStateEvent event; IdleStateEvent event = newIdleStateEvent(IdleState.READER_IDLE, firstReaderIdleEvent);
if (firstReaderIdleEvent) { if (firstReaderIdleEvent) {
firstReaderIdleEvent = false; firstReaderIdleEvent = false;
event = IdleStateEvent.FIRST_READER_IDLE_STATE_EVENT;
} else {
event = IdleStateEvent.READER_IDLE_STATE_EVENT;
} }
channelIdle(ctx, event); channelIdle(ctx, event);
} catch (Throwable t) { } catch (Throwable t) {
ctx.fireExceptionCaught(t); ctx.fireExceptionCaught(t);
@ -406,13 +420,11 @@ public class IdleStateHandler extends ChannelDuplexHandler {
writerIdleTimeout = ctx.executor().schedule( writerIdleTimeout = ctx.executor().schedule(
this, writerIdleTimeNanos, TimeUnit.NANOSECONDS); this, writerIdleTimeNanos, TimeUnit.NANOSECONDS);
try { try {
IdleStateEvent event; IdleStateEvent event = newIdleStateEvent(IdleState.WRITER_IDLE, firstWriterIdleEvent);
if (firstWriterIdleEvent) { if (firstWriterIdleEvent) {
firstWriterIdleEvent = false; firstWriterIdleEvent = false;
event = IdleStateEvent.FIRST_WRITER_IDLE_STATE_EVENT;
} else {
event = IdleStateEvent.WRITER_IDLE_STATE_EVENT;
} }
channelIdle(ctx, event); channelIdle(ctx, event);
} catch (Throwable t) { } catch (Throwable t) {
ctx.fireExceptionCaught(t); ctx.fireExceptionCaught(t);
@ -448,13 +460,11 @@ public class IdleStateHandler extends ChannelDuplexHandler {
allIdleTimeout = ctx.executor().schedule( allIdleTimeout = ctx.executor().schedule(
this, allIdleTimeNanos, TimeUnit.NANOSECONDS); this, allIdleTimeNanos, TimeUnit.NANOSECONDS);
try { try {
IdleStateEvent event; IdleStateEvent event = newIdleStateEvent(IdleState.ALL_IDLE, firstAllIdleEvent);
if (firstAllIdleEvent) { if (firstAllIdleEvent) {
firstAllIdleEvent = false; firstAllIdleEvent = false;
event = IdleStateEvent.FIRST_ALL_IDLE_STATE_EVENT;
} else {
event = IdleStateEvent.ALL_IDLE_STATE_EVENT;
} }
channelIdle(ctx, event); channelIdle(ctx, event);
} catch (Throwable t) { } catch (Throwable t) {
ctx.fireExceptionCaught(t); ctx.fireExceptionCaught(t);