content: package com.grapeshot.halfnes;
  
  import java.io.*;
  import java.lang.reflect.Field;
  import java.nio.charset.StandardCharsets;
  import java.nio.file.Files;
  import java.security.AccessController;
  import java.security.PrivilegedAction;
  
  /**
   * Created by KlausH on 29.11.2015.
   */
  public enum JInputHelper {
  
      ;
  
      private static final String[] NATIVE_LIBRARIES = new String[]{
          // Windows
          "jinput-dx8.dll",
          "jinput-dx8_64.dll",
          "jinput-raw.dll",
          "jinput-raw_64.dll",
          "jinput-wintab.dll",
          "jinput-wintab.dll",
          // Linux
          "libjinput-linux.so",
          "libjinput-linux64.so",
          // OsX (Mac)
          "libjinput-osx.jnilib",};
  
      public static void setupJInput() {
          try {
              File nativesDirectory = createTempDirectory();
              unpackNativeLibraries(nativesDirectory);
              setLibraryPath(nativesDirectory);
              fixInputPluginForWindows8();
          } catch (Exception exception) {
              throw new RuntimeException("Unable to setup native libraries.", exception);
          }
      }
  
      private static void unpackNativeLibraries(File nativesDirectory) throws IOException {
          for (String nativeLibrary : NATIVE_LIBRARIES) {
              unpackNativeLibrary(nativesDirectory, nativeLibrary);
          }
      }
  
      private static void unpackNativeLibrary(File nativesDirectory, String nativeLibrary) throws IOException {
          try (InputStream nativeLibraryInputStream = ClassLoader.getSystemResourceAsStream(nativeLibrary)) {
              File nativeLibraryTempFile = new File(nativesDirectory, nativeLibrary);
              nativeLibraryTempFile.deleteOnExit();
              if (!nativeLibraryTempFile.exists()) {
                  try (BufferedOutputStream nativeLibraryTempFileOutputStream 
                          = new BufferedOutputStream(new FileOutputStream(nativeLibraryTempFile))) {
                      byte[] buffer = new byte[4096];
                      int length;
                      while ((length = nativeLibraryInputStream.read(buffer)) > 0) {
                          nativeLibraryTempFileOutputStream.write(buffer, 0, length);
                      }
                  }
              }
          }
      }
  
      private static File createTempDirectory() throws IOException {
  
          String tmpdir = System.getProperty("java.io.tmpdir") + "/halfnes-" + NES.VERSION;
          System.err.println(tmpdir);
          File f = new File(tmpdir);
          if (!f.exists()) {
              f.mkdir();
          }
  
          //File nativeDirectory = Files.createTempDirectory("halfNES-natives").toFile();
          f.deleteOnExit();
          return f;
      }
  
      private static void setLibraryPath(final File nativesDirectory) throws NoSuchFieldException, IllegalAccessException {
          System.setProperty("java.library.path", nativesDirectory.getAbsolutePath());
          final Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
          fieldSysPath.setAccessible(true);
          fieldSysPath.set(null, null);
      }
  
      private static void fixInputPluginForWindows8() {
          AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
              String os = System.getProperty("os.name", "").trim();
              if (os.startsWith("Windows")) {
                  if (os.startsWith("Windows 8")) {
                      // disable default plugin lookup
                      System.setProperty("jinput.useDefaultPlugin", "false");
                      // set to same as windows 7
                      System.setProperty("net.java.games.input.plugins", "net.java.games.input.DirectAndRawInputEnvironmentPlugin");
                  }
                  if (os.startsWith("Windows 10") || isWindows10()) {
                      // disable default plugin lookup
                      System.setProperty("jinput.useDefaultPlugin", "false");
                      // set fallback to AWT plugin
                      System.setProperty("net.java.games.input.plugins", "net.java.games.input.DirectAndRawInputEnvironmentPlugin");
                  }
              }
              return null;
          });
      }
  
      private static boolean isWindows10() {
          try {
              Process process = Runtime.getRuntime().exec("cmd.exe /c ver");
              BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
              bufferedReader.readLine();
              String line = bufferedReader.readLine();
              process.waitFor();
              return line.contains("10");
          } catch (Exception exception) {
              throw new RuntimeException(exception);
          }
      }
  
  }
  