/**
  * ** Writes the specified line to the specified socket's output stream ** @param socket The
  * socket which's output stream to write to ** @param val The line to write to the socket output
  * stream. A newline is ** appended if it does not already end with one. ** @throws IOException if
  * an error occurs
  */
 protected static void socketWriteLine(Socket socket, String val) throws IOException {
   if (val != null) {
     String lineTerm = ClientSocketThread.getLineTerminator();
     String v = val.endsWith(lineTerm) ? val : (val + lineTerm);
     ClientSocketThread.socketWriteBytes(socket, StringTools.getBytes(v), 0, -1);
   }
 }
    public void run() {
      StringBuffer data = new StringBuffer();
      Print.logDebug("Client:InputThread started");

      while (true) {
        data.setLength(0);
        boolean timeout = false;
        try {
          if (this.readTimeout > 0L) {
            this.socket.setSoTimeout((int) this.readTimeout);
          }
          ClientSocketThread.socketReadLine(this.socket, -1, data);
        } catch (InterruptedIOException ee) { // SocketTimeoutException ee) {
          // error("Read interrupted (timeout) ...");
          if (getRunStatus() != THREAD_RUNNING) {
            break;
          }
          timeout = true;
          // continue;
        } catch (Throwable t) {
          Print.logError("Client:InputThread - " + t);
          t.printStackTrace();
          break;
        }
        if (!timeout || (data.length() > 0)) {
          ClientSocketThread.this.handleMessage(data.toString());
        }
      }

      synchronized (this.threadLock) {
        this.isRunning = false;
        Print.logDebug("Client:InputThread stopped");
        this.threadLock.notify();
      }
    }
  /** ** Main entry point for testing/debugging ** @param argv Comand-line arguments */
  public static void main(String argv[]) {
    RTConfig.setCommandLineArgs(argv);
    String host = RTConfig.getString(ARG_HOST, null);
    int port = RTConfig.getInt(ARG_PORT, 0);

    /* send data */
    if (RTConfig.hasProperty(ARG_SEND)) {
      if (StringTools.isBlank(host)) {
        Print.logError("Target host not specified");
        usage();
      }
      if (port <= 0) {
        Print.logError("Target port not specified");
        usage();
      }
      String dataStr = RTConfig.getString(ARG_SEND, "hello");
      byte data[] =
          dataStr.startsWith("0x") ? StringTools.parseHex(dataStr, null) : dataStr.getBytes();
      ClientSocketThread cst = new ClientSocketThread(host, port);
      try {
        cst.openSocket();
        cst.socketWriteBytes(data);
      } catch (Throwable t) {
        Print.logException("Error", t);
      } finally {
        cst.closeSocket();
      }
      System.exit(0);
    }

    /* receive data */
    if (RTConfig.hasProperty(ARG_RECEIVE)) {
      if (port <= 0) {
        Print.logError("Target port not specified");
        usage();
      }
      if (!StringTools.isBlank(host)) {
        Print.logWarn("Specified 'host' will be ignored");
      }
      Print.logError("Receive not yet implemented ...");
      System.exit(99);
    }

    /* show usage */
    usage();
  }
    public void run() {
      String command = null;
      Print.logInfo("Client:OutputThread started");

      while (true) {

        /* wait for commands */
        synchronized (this.cmdList) {
          while ((this.cmdList.size() <= 0) && (getRunStatus() == THREAD_RUNNING)) {
            try {
              this.cmdList.wait(5000L);
            } catch (Throwable t) {
              /*ignore*/
            }
          }
          if (getRunStatus() != THREAD_RUNNING) {
            break;
          }
          command = this.cmdList.remove(0).toString();
        }

        /* send commands */
        try {
          ClientSocketThread.socketWriteLine(this.socket, command);
        } catch (Throwable t) {
          Print.logError("Client:OutputThread - " + t);
          t.printStackTrace();
          break;
        }
      }

      if (getRunStatus() == THREAD_RUNNING) {
        Print.logWarn("Client:OutputThread stopped due to error");
      } else {
        Print.logInfo("Client:OutputThread stopped");
      }

      synchronized (this.threadLock) {
        this.isRunning = false;
        Print.logInfo("Client:OutputThread stopped");
        this.threadLock.notify();
      }
    }
 /**
  * ** Reads a line from the socket input stream ** @param maxLen The maximum length of of the line
  * to read ** @param sb The string buffer to use ** @throws IOException if an error occurs or the
  * server has stopped
  */
 public String socketReadLine(int maxLen, StringBuffer sb) throws IOException {
   return ClientSocketThread.socketReadLine(this.socket, maxLen, sb);
 }
 /**
  * ** Reads a line from the socket input stream ** @param maxLen The maximum length of the line to
  * read ** @throws IOException if an error occurs or the server has stopped
  */
 public String socketReadLine(int maxLen) throws IOException {
   return ClientSocketThread.socketReadLine(this.socket, maxLen, null);
 }
 /**
  * ** Writes the specified line to the socket output stream ** @param val The line to write to the
  * socket output stream. A newline is ** appended if it does not already end with one. ** @throws
  * IOException if an error occurs
  */
 public void socketWriteLine(String val) throws IOException {
   ClientSocketThread.socketWriteLine(this.socket, val);
 }
 /**
  * ** Writes the specified String to the specified socket's output stream ** @param socket The
  * socket which's output stream to write to ** @param val The String to write to the socket output
  * stream. ** @throws IOException if an error occurs
  */
 protected static void socketWriteString(Socket socket, String val) throws IOException {
   if (val != null) {
     ClientSocketThread.socketWriteBytes(socket, StringTools.getBytes(val), 0, -1);
   }
 }
 /**
  * ** Writes the specified StringBuffer to the socket output stream ** @param val The StringBuffer
  * to write to the socket output stream. ** @throws IOException if an error occurs
  */
 public void socketWriteString(StringBuffer val) throws IOException {
   ClientSocketThread.socketWriteString(this.socket, val);
 }
 /**
  * ** Writes <code>length</code> bytes from the specified byte array ** starting at <code>offset
  * </code> to the socket output stream. ** @param b The byte array to write to the socket output
  * stream ** @param offset The start offset in the data to begin writing at ** @param length The
  * length of the data. Normally <code>b.length</code> ** @throws IOException if an error occurs
  */
 public void socketWriteBytes(byte b[], int offset, int length) throws IOException {
   ClientSocketThread.socketWriteBytes(this.socket, b, offset, length);
 }
 /**
  * ** Writes the specified byte array to the socket output stream ** @param b The byte array to
  * write to the socket output stream ** @throws IOException if an error occurs
  */
 public void socketWriteBytes(byte b[]) throws IOException {
   ClientSocketThread.socketWriteBytes(this.socket, b, 0, -1);
 }