Make "bazel info server_pid" work on Windows.

This is the first actual use of Windows JNI!

Also a cleanup of ProcessUtils. Injecting a mock implementation was never used.

--
MOS_MIGRATED_REVID=126068832
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index ab08d72..7f0f399 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -256,6 +256,7 @@
         ":shell",
         ":unix",
         ":vfs",
+        ":windows",
         "//src/main/java/com/google/devtools/common/options",
         "//third_party:guava",
         "//third_party:jsr305",
diff --git a/src/main/java/com/google/devtools/build/lib/shell/Consumers.java b/src/main/java/com/google/devtools/build/lib/shell/Consumers.java
index 37df646..972bfa8 100644
--- a/src/main/java/com/google/devtools/build/lib/shell/Consumers.java
+++ b/src/main/java/com/google/devtools/build/lib/shell/Consumers.java
@@ -129,8 +129,7 @@
   /**
    * This consumer sends the input to a stream while consuming it.
    */
-  private static class StreamingConsumer extends FutureConsumption
-                                         implements OutputConsumer {
+  private static class StreamingConsumer extends FutureConsumption {
     private OutputStream out;
 
     StreamingConsumer(OutputStream out) {
@@ -158,8 +157,7 @@
    * while consuming it. This accumulated stream can be obtained by
    * calling {@link #getAccumulatedOut()}.
    */
-  private static class AccumulatingConsumer extends FutureConsumption
-                                            implements OutputConsumer {
+  private static class AccumulatingConsumer extends FutureConsumption {
     private ByteArrayOutputStream out = new ByteArrayOutputStream();
 
     @Override
@@ -180,8 +178,7 @@
   /**
    * This consumer just discards whatever it reads.
    */
-  private static class DiscardingConsumer extends FutureConsumption
-                                          implements OutputConsumer {
+  private static class DiscardingConsumer extends FutureConsumption {
     private DiscardingConsumer() {
     }
 
diff --git a/src/main/java/com/google/devtools/build/lib/util/OsUtils.java b/src/main/java/com/google/devtools/build/lib/util/OsUtils.java
index e633b4f..16d75b0 100644
--- a/src/main/java/com/google/devtools/build/lib/util/OsUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/util/OsUtils.java
@@ -45,11 +45,15 @@
   }
 
   private static boolean jniLibsAvailable() {
+    if (OS.getCurrent() == OS.WINDOWS) {
+      return true;
+    }
+
     if ("0".equals(System.getProperty("io.bazel.UnixFileSystem"))) {
       return false;
     }
-    // JNI libraries work fine on Windows, but at the moment we are not using any.
-    return OS.getCurrent() != OS.WINDOWS;
+
+    return true;
   }
 
   // Force JNI linking at a moment when we have 'installBase' handy, and print
diff --git a/src/main/java/com/google/devtools/build/lib/util/ProcessUtils.java b/src/main/java/com/google/devtools/build/lib/util/ProcessUtils.java
index acbdb8c..c6a4758 100644
--- a/src/main/java/com/google/devtools/build/lib/util/ProcessUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/util/ProcessUtils.java
@@ -15,50 +15,13 @@
 package com.google.devtools.build.lib.util;
 
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
+import com.google.devtools.build.lib.windows.WindowsProcesses;
 
 /**
  * OS Process related utilities.
- *
- * <p>Default implementation forwards all requests to
- * {@link com.google.devtools.build.lib.unix.ProcessUtils}. The default implementation
- * can be overridden by {@code #setImplementation(ProcessUtilsImpl)} method.
  */
 @ThreadSafe
 public final class ProcessUtils {
-
-  /**
-   * Describes implementation to which all {@code ProcessUtils} requests are
-   * forwarded.
-   */
-  public interface ProcessUtilsImpl {
-    /** @see ProcessUtils#getgid() */
-    int getgid();
-
-    /** @see ProcessUtils#getpid() */
-    int getpid();
-
-    /** @see ProcessUtils#getuid() */
-    int getuid();
-  }
-
-  private volatile static ProcessUtilsImpl implementation = new ProcessUtilsImpl() {
-
-    @Override
-    public int getgid() {
-      return com.google.devtools.build.lib.unix.ProcessUtils.getgid();
-    }
-
-    @Override
-    public int getpid() {
-      return com.google.devtools.build.lib.unix.ProcessUtils.getpid();
-    }
-
-    @Override
-    public int getuid() {
-      return com.google.devtools.build.lib.unix.ProcessUtils.getuid();
-    }
-  };
-
   private ProcessUtils() {
     // prevent construction.
   }
@@ -67,20 +30,32 @@
    * @return the real group ID of the current process.
    */
   public static int getgid() {
-    return implementation.getgid();
+    if (OS.getCurrent() == OS.WINDOWS) {
+      throw new UnsupportedOperationException();
+    } else {
+      return com.google.devtools.build.lib.unix.ProcessUtils.getgid();
+    }
   }
 
   /**
    * @return the process ID of this process.
    */
   public static int getpid() {
-    return implementation.getpid();
+    if (OS.getCurrent() == OS.WINDOWS) {
+      return WindowsProcesses.getpid();
+    } else {
+      return com.google.devtools.build.lib.unix.ProcessUtils.getpid();
+    }
   }
 
   /**
    * @return the real user ID of the current process.
    */
   public static int getuid() {
-    return implementation.getuid();
+    if (OS.getCurrent() == OS.WINDOWS) {
+      throw new UnsupportedOperationException();
+    } else {
+      return com.google.devtools.build.lib.unix.ProcessUtils.getuid();
+    }
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsProcesses.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsProcesses.java
index f23508d..f6d6260 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsProcesses.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsProcesses.java
@@ -18,5 +18,25 @@
  * Process management on Windows.
  */
 public class WindowsProcesses {
-  public static native String helloWorld(int arg, String fruit);
+  private static boolean jniLoaded = false;
+  private WindowsProcesses() {
+    // Prevent construction
+  }
+
+  private static native String helloWorld(int arg, String fruit);
+  private static native int nativeGetpid();
+
+  public static int getpid() {
+    ensureJni();
+    return nativeGetpid();
+  }
+
+  private static synchronized void ensureJni() {
+    if (jniLoaded) {
+      return;
+    }
+
+    System.loadLibrary("windows_jni");
+    jniLoaded = true;
+  }
 }