public synchronized void stop() {
    if (channelClazz == null) {
      return;
    }

    if (protocolHandler != null) {
      protocolHandler.close();
    }

    if (batchFlusherFuture != null) {
      batchFlusherFuture.cancel(false);

      flusher.cancel();

      flusher = null;

      batchFlusherFuture = null;
    }

    // serverChannelGroup has been unbound in pause()
    if (serverChannelGroup != null) {
      serverChannelGroup.close().awaitUninterruptibly();
    }

    if (channelGroup != null) {
      ChannelGroupFuture future = channelGroup.close().awaitUninterruptibly();

      if (!future.isSuccess()) {
        ActiveMQServerLogger.LOGGER.nettyChannelGroupError();
        Iterator<Channel> iterator = future.group().iterator();
        while (iterator.hasNext()) {
          Channel channel = iterator.next();
          if (channel.isActive()) {
            ActiveMQServerLogger.LOGGER.nettyChannelStillOpen(channel, channel.remoteAddress());
          }
        }
      }
    }

    // Shutdown the EventLoopGroup if no new task was added for 100ms or if
    // 3000ms elapsed.
    eventLoopGroup.shutdownGracefully(100, 3000, TimeUnit.MILLISECONDS);
    eventLoopGroup = null;

    channelClazz = null;

    for (Connection connection : connections.values()) {
      listener.connectionDestroyed(connection.getID());
    }

    connections.clear();

    if (notificationService != null) {
      TypedProperties props = new TypedProperties();
      props.putSimpleStringProperty(
          new SimpleString("factory"), new SimpleString(NettyAcceptorFactory.class.getName()));
      props.putSimpleStringProperty(new SimpleString("host"), new SimpleString(host));
      props.putIntProperty(new SimpleString("port"), port);
      Notification notification =
          new Notification(null, CoreNotificationType.ACCEPTOR_STOPPED, props);
      try {
        notificationService.sendNotification(notification);
      } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }

    paused = false;
  }
 /**
  * Transfers the Netty channel that has been created outside of this NettyAcceptor to control it
  * and configure it according to this NettyAcceptor setting.
  *
  * @param channel A Netty channel created outside this NettyAcceptor.
  */
 public void transfer(Channel channel) {
   channel.pipeline().addLast(protocolHandler.getProtocolDecoder());
 }