/** @throws Exception */
  @AfterClass
  public static void tearDownAfterClass() throws Exception {
    String methodName = Utility.getMethodName();
    LoggingUtilities.banner(log, cclass, methodName);

    try {
      if (clientFactory != null) {
        clientFactory.close();
        clientFactory.disconnect();
      }
    } catch (Exception exception) {
      log.log(Level.SEVERE, "caught exception:", exception);
    }
  }
  /** @throws Exception */
  @BeforeClass
  public static void setUpBeforeClass() throws Exception {

    try {
      String methodName = Utility.getMethodName();
      LoggingUtilities.banner(log, cclass, methodName);

      serverURI = TestProperties.getServerURI();
      clientFactory = new MqttClientFactoryPaho();
      clientFactory.open();
    } catch (Exception exception) {
      log.log(Level.SEVERE, "caught exception:", exception);
      throw exception;
    }
  }
  /**
   * Test that a client actively doing work can be taken over
   *
   * @throws Exception
   */
  @Test
  public void testLiveTakeOver() throws Exception {
    String methodName = Utility.getMethodName();
    LoggingUtilities.banner(log, cclass, methodName);
    log.entering(className, methodName);

    IMqttClient mqttClient = null;
    try {
      FirstClient firstClient = new FirstClient();
      Thread firstClientThread = new Thread(firstClient);
      log.info("Starting the firstClient thread");
      firstClientThread.start();
      log.info("firstClientThread Started");

      firstClient.waitForState(FirstClientState.READY);

      log.fine("telling the 1st client to go and let it publish for 2 seconds");
      // Tell the first client to go and let it publish for a couple of seconds
      firstClient.setState(FirstClientState.RUNNING);
      Thread.sleep(2000);

      log.fine("Client has been run for 2 seconds, now taking over connection");

      // Now lets take over the connection
      // Create a second MQTT client connection with the same clientid. The
      // server should spot this and kick the first client connection off.
      // To do this from the same box the 2nd client needs to use either
      // a different form of persistent store or a different locaiton for
      // the store to the first client.
      // MqttClientPersistence persist = new MemoryPersistence();
      mqttClient = clientFactory.createMqttClient(serverURI, ClientId, null);

      MqttV3Receiver mqttV3Receiver =
          new MqttV3Receiver(mqttClient, LoggingUtilities.getPrintStream());
      mqttClient.setCallback(mqttV3Receiver);
      MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
      mqttConnectOptions.setCleanSession(false);
      mqttConnectOptions.setWill("WillTopic", "payload".getBytes(), 2, true);
      log.info("Connecting...(serverURI:" + serverURI + ", ClientId:" + ClientId);
      mqttClient.connect(mqttConnectOptions);

      // We should have taken over the first Client's subscription...we may have some
      // of his publishes arrive.
      // NOTE: as a different persistence is used for the second client any inflight
      // publications from the client will not be recovered / restarted. This will
      // leave debris on the server.
      log.fine(
          "We should have taken over the first Client's subscription...we may have some of his publishes arrive.");
      // Ignore his publishes that arrive...
      ReceivedMessage oldMsg;
      do {
        oldMsg = mqttV3Receiver.receiveNext(1000);
      } while (oldMsg != null);

      log.fine("Now check we have grabbed his subscription by publishing..");
      // Now check we have grabbed his subscription by publishing..
      byte[] payload =
          ("Message payload from second client " + getClass().getName() + "." + methodName)
              .getBytes();
      MqttTopic mqttTopic = mqttClient.getTopic(FirstSubTopicString);
      log.info("Publishing to..." + FirstSubTopicString);
      mqttTopic.publish(payload, 1, false);
      log.info("Publish sent, checking for receipt...");

      boolean ok = mqttV3Receiver.validateReceipt(FirstSubTopicString, 1, payload);
      if (!ok) {
        throw new Exception("Receive failed");
      }
    } catch (Exception exception) {
      log.throwing(className, methodName, exception);
      throw exception;
    } finally {
      try {
        mqttClient.disconnect();
        log.info("Disconnecting...");
        mqttClient.close();
        log.info("Close...");
      } catch (Exception exception) {
        log.throwing(className, methodName, exception);
        throw exception;
      }
    }

    log.exiting(className, methodName);
  }