/**
  * @see
  *     org.apache.james.imap.api.process.ImapProcessor#process(org.apache.james.imap.api.ImapMessage,
  *     org.apache.james.imap.api.process.ImapProcessor.Responder,
  *     org.apache.james.imap.api.process.ImapSession)
  */
 @Override
 @SuppressWarnings("unchecked")
 public void process(ImapMessage message, Responder responder, ImapSession session) {
   final boolean isAcceptable = isAcceptable(message);
   if (isAcceptable) {
     doProcess((M) message, responder, session);
   } else {
     next.process(message, responder, session);
   }
 }
  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    ImapSession session = (ImapSession) attributes.get(ctx.getChannel());
    ImapResponseComposer response = (ImapResponseComposer) ctx.getAttachment();
    ImapMessage message = (ImapMessage) e.getMessage();
    ChannelPipeline cp = ctx.getPipeline();

    try {
      if (cp.get(NettyConstants.EXECUTION_HANDLER) != null) {
        cp.addBefore(
            NettyConstants.EXECUTION_HANDLER, NettyConstants.HEARTBEAT_HANDLER, heartbeatHandler);
      } else {
        cp.addBefore(
            NettyConstants.CORE_HANDLER, NettyConstants.HEARTBEAT_HANDLER, heartbeatHandler);
      }
      final ResponseEncoder responseEncoder = new ResponseEncoder(encoder, response, session);
      processor.process(message, responseEncoder, session);

      if (session.getState() == ImapSessionState.LOGOUT) {
        // Make sure we close the channel after all the buffers were flushed out
        Channel channel = ctx.getChannel();
        if (channel.isConnected()) {
          channel.write(ChannelBuffers.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
        }
      }
      final IOException failure = responseEncoder.getFailure();

      if (failure != null) {
        final Logger logger = session.getLog();
        logger.info(failure.getMessage());
        if (logger.isDebugEnabled()) {
          logger.debug("Failed to write " + message, failure);
        }
        throw failure;
      }
    } finally {
      ctx.getPipeline().remove(NettyConstants.HEARTBEAT_HANDLER);
    }

    super.messageReceived(ctx, e);
  }