@Override
  public Future<Boolean> connect(final String clientId) throws Exception {

    if (isConnected()) {
      throw new Exception("You are already connected");
    }

    // keep track of the original one, so we can detect change
    this.originalClientId = clientId;

    // this will help us do the connect synchronously
    connectLatch = new CountDownLatch(1);
    final Future connectFuture = connection.connect();

    FutureTask<Boolean> asdf =
        new FutureTask<Boolean>(
            new Callable<Boolean>() {

              @Override
              public Boolean call() {
                // TODO: notify callers somehow?

                try {
                  connectFuture.get(45, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                  e.printStackTrace();
                } catch (ExecutionException e) {
                  e.printStackTrace();
                } catch (TimeoutException e) {
                  e.printStackTrace();
                }

                if (connection.isConnected()) {
                  connection.send(new ConnectCommand(clientId));

                  // block while the signal server is thinking/hanging.
                  try {
                    connectLatch.await(45, TimeUnit.SECONDS);
                  } catch (InterruptedException e) {
                    e.printStackTrace();
                  }
                }

                final boolean result = isConnected();

                // queue it up, or else the "connect()" call will still block while the slow-ass
                // observers fire.
                connectEvent.notifyObservers(this, result);

                return result;
              }
            });

    // this background thread stops us from blocking.
    executor.execute(asdf);

    return asdf;
  }
  public SocketSignalProvider(SignalConnection conn) {
    this.connection = conn;

    this.link(connection);
    this.link(connectEvent);
    this.link(newClientIdEvent);
    this.link(signalEvent);

    connection.onMessageReceived(
        new Observer<Command>() {
          /**
           * The NettySignalConnection will call this method when there's an event from the remote
           * signal server.
           *
           * @param sender The sender might not be the same object every time, so we'll let it just
           *     be object, rather than generics.
           * @param item - Rich object representing the notification.
           */
          @Override
          public void notify(Object sender, Command item) {
            if (item instanceof ConnectCommand) {
              ConnectCommand command = (ConnectCommand) item;
              if (command.isSuccessful()) {
                // copy it over for stale checking
                originalClientId = clientId;

                clientId = command.getClientId();

                if (!StringUtil.equals(clientId, originalClientId)) {
                  // not the same, lets announce
                  // announce on a separate thread
                  newClientIdEvent.notifyObservers(this, clientId);
                }

                if (connectLatch != null) {
                  // we need to countDown the latch, when it hits zero (after this call)
                  // the connect Future will complete. This gives the caller a way to block on our
                  // connection
                  connectLatch.countDown();
                }
              }
            }

            //                if (item instanceof SignalSignalServerMessage){
            //                    // we're being notified that we received a signal.
            //                    SignalEvent signalEvent = new SignalEvent();
            //                    signalEvent.setSessionKey(item.getSubscriptionId());
            //                    signalEvent.setSignals(signals);
            //                }

          }
        });
  }
 @Override
 public boolean isConnected() {
   return connection.isConnected() && !StringUtil.isNullOrEmpty(clientId);
 }
 @Override
 public Future<Void> disconnect() throws Exception {
   return connection.disconnect();
 }