/**
   * Start a HyperGateClient
   *
   * <p>for that case use
   *
   * @throws Exception
   */
  @Override
  public void start() throws Exception {

    if (this.running) {
      throw new InstantiationException("HyperGate client " + this.getName() + "is running");
    }

    // Configure the client.
    // TODO make it more robust & speedy implements Kryo serializer
    this.channelFactory =
        new NioClientSocketChannelFactory(
            // TODO implement other executors
            Executors.newCachedThreadPool(), Executors.newCachedThreadPool());

    this.clientBootstrap = new ClientBootstrap(channelFactory);

    ChannelPipelineFactory channelPipelineFactory =
        new ChannelPipelineFactory() {
          public ChannelPipeline getPipeline() throws Exception {
            return Channels.pipeline(
                // TODO make Encoder & Decoder - like a Strategy Pattern, and changeable via
                // external settings
                //                        new KryoObjectEncoder(),
                //                        new
                // KryoObjectDecoder(ClassResolvers.cacheDisabled(getClass().getClassLoader()))
                // TODO #6
                new ObjectEncoder(),
                new ObjectDecoder(ClassResolvers.cacheDisabled(getClass().getClassLoader())),
                new SimpleChannelUpstreamHandler() {

                  @Override
                  public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
                      throws Exception {
                    if (e instanceof ChannelStateEvent
                        && ((ChannelStateEvent) e).getState() != ChannelState.INTEREST_OPS) {
                      LOG.info(e.toString());
                    }
                    super.handleUpstream(ctx, e);
                  }

                  @Override
                  public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent event) {
                    channel = event.getChannel();
                    // Send the first message
                    // channel.write(firstMessage);
                  }

                  @Override
                  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
                    // Get
                    serverListener(e.getMessage());
                    ctx.sendUpstream(e);

                    // e.getChannel().write(e.getStatus());
                    // e.getChannel().close();
                  }

                  @Override
                  public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
                    LOG.warn("Unexpected exception from downstream.", e.getCause());
                    e.getChannel().close();
                  }
                });
          }
        };

    // Set up the pipeline factory.
    this.clientBootstrap.setPipelineFactory(channelPipelineFactory);

    // Start the connection attempt.
    // ChannelFuture channelFuture = this.clientBootstrap.connect(new InetSocketAddress(host,
    // setPort));
    LOG.debug("CLIENT GOING TO CONNECT - host:" + host + " post:" + port);
    this.channelFuture = this.clientBootstrap.connect(new InetSocketAddress(host, port));

    // INFO

    // correct shut down a client
    // see http://netty.io/3.6/guide/#start.12 - 9.  Shutting Down Your Application

    // http://stackoverflow.com/questions/10911988/shutting-down-netty-server-when-client-connections-are-open
    //    Netty Server Shutdown
    //
    //    Close server channel
    //    Shutdown boss and worker executor
    //    Release server bootstrap resource
    //    Example code
    //
    //    ChannelFuture cf = serverChannel.close();
    //    cf.awaitUninterruptibly();
    //    bossExecutor.shutdown();
    //    workerExecutor.shutdown();
    //    thriftServer.releaseExternalResources();

    // TODO Need to repair it

    boolean goAway = false;
    long countGoAway = 0;
    final long stepGoAway = 50; // ms

    LOG.warn("Warming up 0.6.0-SNAPSHOT ...");
    while (goAway == false | countGoAway < (SERVER_CONNECTION_TIMEOUT / stepGoAway)) {

      Thread.sleep(stepGoAway);
      if (!channelFuture.isSuccess()) {
        this.running = false;
        goAway = true;
      } else {
        this.running = true;
        goAway = true;
        countGoAway = (SERVER_CONNECTION_TIMEOUT / stepGoAway) + 10;
      }
      countGoAway++;
      LOG.warn(
          "Count down for connection tomeout:"
              + countGoAway * stepGoAway
              + ":ms future:"
              + channelFuture.isSuccess()
              + " running:"
              + this.running);
    }

    if (this.running == false) {
      LOG.warn("After ");
      channelFuture.getCause().printStackTrace();
      channelFactory.releaseExternalResources();
      channelFuture = null;
    }
  }
 @Override
 public void close() {
   allChannels.close().awaitUninterruptibly();
   channelFactory.releaseExternalResources();
 }
 private void shutDownChannelFuture(ChannelFuture channelFutureLocal) {
   channelFutureLocal.getCause().printStackTrace();
   channelFactory.releaseExternalResources();
   channelFutureLocal = null;
   running = false;
 }