public static final void printThreadDump() {
    File javaHome = StaticEntity.getJDKWorkingDirectory();

    if (javaHome == null) {
      KoLmafia.updateDisplay(
          "To use this feature, you must run KoLmafia with a JDK instead of a JRE.");
      return;
    }

    String pid = StaticEntity.getProcessId();

    if (pid == null) {
      return;
    }

    KoLmafia.updateDisplay("Generating thread dump for KoLmafia process id " + pid + "...");

    Runtime runtime = Runtime.getRuntime();

    StringBuffer sb = new StringBuffer();

    try {
      String[] command = new String[2];

      if (System.getProperty("os.name").startsWith("Windows")) {
        command[0] = new File(javaHome, "bin/jstack.exe").getPath();
      } else {
        command[0] = new File(javaHome, "bin/jstack").getPath();
      }

      command[1] = pid;

      Process process = runtime.exec(command);
      BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

      String line;

      while ((line = reader.readLine()) != null) {
        sb.append(line);
        sb.append(KoLConstants.LINE_BREAK);
      }

      reader.close();
    } catch (IOException e) {
      e.printStackTrace();
    }

    boolean shouldOpenStream = !RequestLogger.isDebugging();

    if (shouldOpenStream) {
      RequestLogger.openDebugLog();
    }

    RequestLogger.getDebugStream().println(sb.toString());

    if (shouldOpenStream) {
      RequestLogger.closeDebugLog();
    }
  }
 @Override
 public String apply(String request) {
   final RequestLogger logger = THREAD_LOG.get();
   logger.requestStart(request);
   final String response = super.apply(request);
   logger.requestEnd(request, response);
   return response;
 }
  public static final void printStackTrace(
      final Throwable t, final String message, final boolean printOnlyCause) {
    // Next, print all the information to the debug log so that
    // it can be sent.

    boolean shouldOpenStream = !RequestLogger.isDebugging();
    if (shouldOpenStream) {
      RequestLogger.openDebugLog();
    }

    if (message.startsWith("Backtrace")) {
      StaticEntity.backtraceTrigger = null;
      KoLmafia.updateDisplay("Backtrace triggered, debug log printed.");
    } else if (!message.equals("")) {
      KoLmafia.updateDisplay(message);
    } else {
      t.printStackTrace();
      /*java.lang.IndexOutOfBoundsException: Index: 0, Tab count: 0
      	at javax.swing.JTabbedPane.checkIndex(JTabbedPane.java:1738)
      	at javax.swing.JTabbedPane.setSelectedIndex(JTabbedPane.java:572)
      	at net.sourceforge.kolmafia.swingui.listener.ChatEntryListener.execute(ChatEntryListener.java:64)
      	at net.sourceforge.kolmafia.swingui.listener.ThreadedListener.run(ThreadedListener.java:244)
      	at net.sourceforge.kolmafia.RequestThread$ThreadWrappedRunnable.run(RequestThread.java:342)
      */
      KoLmafia.updateDisplay("Unexpected error, debug log printed.");
    }

    Throwable cause = t.getCause();

    if (cause == null || !printOnlyCause) {
      StaticEntity.printStackTrace(t, message, RequestLogger.getDebugStream());
    }

    if (cause != null) {
      StaticEntity.printStackTrace(cause, message, RequestLogger.getDebugStream());
    }

    if (shouldOpenStream) {
      RequestLogger.closeDebugLog();
    }
  }
  public static final void printRequestData(final GenericRequest request) {
    if (request == null) {
      return;
    }

    boolean shouldOpenStream = !RequestLogger.isDebugging();
    if (shouldOpenStream) {
      RequestLogger.openDebugLog();
    }

    RequestLogger.updateDebugLog();
    RequestLogger.updateDebugLog("" + request.getClass() + ": " + request.getURLString());
    RequestLogger.updateDebugLog(
        KoLConstants.LINE_BREAK_PATTERN.matcher(request.responseText).replaceAll(""));
    RequestLogger.updateDebugLog();

    if (shouldOpenStream) {
      RequestLogger.closeDebugLog();
    }
  }
  public static final void generateHeapDump() {
    File javaHome = StaticEntity.getJDKWorkingDirectory();

    if (javaHome == null) {
      KoLmafia.updateDisplay(
          "To use this feature, you must run KoLmafia with a JDK instead of a JRE.");
      return;
    }

    String pid = StaticEntity.getProcessId();

    if (pid == null) {
      return;
    }

    KoLmafia.updateDisplay("Generating heap dump for KoLmafia process id " + pid + "...");

    Runtime runtime = Runtime.getRuntime();

    StringBuffer sb = new StringBuffer();

    try {
      String[] command = new String[3];

      if (System.getProperty("os.name").startsWith("Windows")) {
        command[0] = new File(javaHome, "bin/jmap.exe").getPath();
      } else {
        command[0] = new File(javaHome, "bin/jmap").getPath();
      }

      String javaVersion = System.getProperty("java.runtime.version");

      if (javaVersion.contains("1.5.0_")) {
        command[1] = "-heap:format=b";
      } else {
        int fileIndex = 0;
        String jmapFileName = null;
        File jmapFile = null;

        do {
          ++fileIndex;
          jmapFileName = "kolmafia" + fileIndex + ".hprof";
          jmapFile = new File(UtilityConstants.ROOT_LOCATION, jmapFileName);
        } while (jmapFile.exists());

        command[1] = "-dump:format=b,file=" + jmapFileName;
      }

      command[2] = pid;

      Process process = runtime.exec(command, new String[0], UtilityConstants.ROOT_LOCATION);

      BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

      String line;

      while ((line = reader.readLine()) != null) {
        sb.append(line);
        sb.append(KoLConstants.LINE_BREAK);
      }

      reader.close();
    } catch (IOException e) {
      e.printStackTrace();
    }

    boolean shouldOpenStream = !RequestLogger.isDebugging();

    if (shouldOpenStream) {
      RequestLogger.openDebugLog();
    }

    RequestLogger.getDebugStream().println(sb.toString());

    if (shouldOpenStream) {
      RequestLogger.closeDebugLog();
    }
  }
  public static final String getProcessId() {
    File javaHome = StaticEntity.getJDKWorkingDirectory();

    if (javaHome == null) {
      KoLmafia.updateDisplay(
          "To use this feature, you must run KoLmafia with a JDK instead of a JRE.");

      return null;
    }

    Runtime runtime = Runtime.getRuntime();

    String pid = null;

    try {
      String[] command = new String[2];

      if (System.getProperty("os.name").startsWith("Windows")) {
        command[0] = new File(javaHome, "bin/jps.exe").getPath();
      } else {
        command[0] = new File(javaHome, "bin/jps").getPath();
      }

      command[1] = "-l";

      Process process = runtime.exec(command);
      BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

      String line;

      StringBuffer sb = new StringBuffer();

      while ((pid == null) && (line = reader.readLine()) != null) {
        sb.append(line);
        sb.append(KoLConstants.LINE_BREAK);

        if (line.indexOf("KoLmafia") != -1) {
          pid = line.substring(0, line.indexOf(' '));
        }

        boolean shouldOpenStream = !RequestLogger.isDebugging();

        if (shouldOpenStream) {
          RequestLogger.openDebugLog();
        }

        RequestLogger.getDebugStream().println(sb.toString());

        if (shouldOpenStream) {
          RequestLogger.closeDebugLog();
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    }

    if (pid != null) {
      return pid;
    }

    KoLmafia.updateDisplay("Unable to determine KoLmafia process id.");

    return null;
  }