docs: static boolean detect(final String detectPattern, final String failurePattern, final long timeout,
                            final int maxLines, final InputStreamReader reader,
                            final PartialLineBuffer buffer) throws IOException, ThreshholdException {
          if (null == detectPattern && null == failurePattern) {
              throw new IllegalArgumentException("detectPattern or failurePattern required");
          }
          long start = System.currentTimeMillis();
          int linecount = 0;
          final Pattern success;
          if (null != detectPattern) {
              success = Pattern.compile(detectPattern);
          } else {
              success = null;
          }
          final Pattern failure;
          if (null != failurePattern) {
              failure = Pattern.compile(failurePattern);
          } else {
              failure = null;
          }
          outer:
          while (System.currentTimeMillis() < start + timeout && linecount < maxLines && !Thread.currentThread()
              .isInterrupted()) {
              //check buffer first, it may already contain data
              String line = buffer.readLine();
              while (null != line) {
                  logger.debug("read line: " + line);
                  start = System.currentTimeMillis();
                  linecount++;
                  if (null != success && success.matcher(line).matches()) {
                      logger.debug("success matched");
                      return true;
                  } else if (null != failure && failure.matcher(line).matches()) {
                      logger.debug("failure matched");
                      return false;
                  }
                  if (linecount >= maxLines) {
                      break outer;
                  }
                  line = buffer.readLine();
              }
              line = buffer.getPartialLine();
              if (null != line) {
                  logger.debug("read partial: " + line);
                  if (null != success && success.matcher(line).matches()) {
                      logger.debug("success matched partial");
                      buffer.clearPartial();
                      return true;
                  } else if (null != failure && failure.matcher(line).matches()) {
                      logger.debug("failure matched partial");
                      buffer.clearPartial();
                      return false;
                  }else {
                      buffer.unmarkPartial();
                  }
              }
  
              if (!reader.ready()) {
                  try {
                      Thread.sleep(500);
                  } catch (InterruptedException e) {
                      Thread.currentThread().interrupt();
                      return false;
                  }
                  continue;
              }
              final int c = buffer.read(reader);
              if (c < 0) {
                  //end of stream
                  logger.debug("end of input");
              } else if (c > 0) {
                  logger.debug("read " + c);
              }
  
          }
          if (Thread.currentThread().isInterrupted()) {
              logger.debug("detect interrupted");
          }
          if (linecount >= maxLines) {
              logger.debug("max input lines");
              throw new ThreshholdException(maxLines, ThresholdType.lines);
          } else if (System.currentTimeMillis() >= start + timeout) {
              logger.debug("max timeout");
              throw new ThreshholdException(timeout, ThresholdType.milliseconds);
          } else {
              //
              return false;
          }
      }