content: package org.rocksdb;
  
  import java.io.*;
  import java.nio.file.Files;
  import java.nio.file.StandardCopyOption;
  
  import org.rocksdb.util.Environment;
  
  /**
   * This class is used to load the RocksDB shared library from within the jar.
   * The shared library is extracted to a temp folder and loaded from there.
   */
  public class NativeLibraryLoader {
    //singleton
    private static final NativeLibraryLoader instance = new NativeLibraryLoader();
    private static boolean initialized = false;
  
    private static final String sharedLibraryName = Environment.getSharedLibraryName("rocksdb");
    private static final String jniLibraryName = Environment.getJniLibraryName("rocksdb");
    private static final String jniLibraryFileName = Environment.getJniLibraryFileName("rocksdb");
    private static final String tempFilePrefix = "librocksdbjni";
    private static final String tempFileSuffix = Environment.getJniLibraryExtension();
  
    /**
     * Get a reference to the NativeLibraryLoader
     *
     * @return The NativeLibraryLoader
     */
    public static NativeLibraryLoader getInstance() {
      return instance;
    }
  
    /**
     * Firstly attempts to load the library from <i>java.library.path</i>,
     * if that fails then it falls back to extracting
     * the library from the classpath
     * {@link org.rocksdb.NativeLibraryLoader#loadLibraryFromJar(java.lang.String)}
     *
     * @param tmpDir A temporary directory to use
     *   to copy the native library to when loading from the classpath.
     *   If null, or the empty string, we rely on Java's
     *   {@link java.io.File#createTempFile(String, String)}
     *   function to provide a temporary location.
     *   The temporary file will be registered for deletion
     *   on exit.
     *
     * @throws java.io.IOException if a filesystem operation fails.
     */
    public synchronized void loadLibrary(final String tmpDir) throws IOException {
      try {
          System.loadLibrary(sharedLibraryName);
      } catch(final UnsatisfiedLinkError ule1) {
        try {
          System.loadLibrary(jniLibraryName);
        } catch(final UnsatisfiedLinkError ule2) {
          loadLibraryFromJar(tmpDir);
        }
      }
    }
  
    /**
     * Attempts to extract the native RocksDB library
     * from the classpath and load it
     *
     * @param tmpDir A temporary directory to use
     *   to copy the native library to. If null,
     *   or the empty string, we rely on Java's
     *   {@link java.io.File#createTempFile(String, String)}
     *   function to provide a temporary location.
     *   The temporary file will be registered for deletion
     *   on exit.
     *
     * @throws java.io.IOException if a filesystem operation fails.
     */
    void loadLibraryFromJar(final String tmpDir)
        throws IOException {
      if (!initialized) {
        System.load(loadLibraryFromJarToTemp(tmpDir).getAbsolutePath());
        initialized = true;
      }
    }
  
    File loadLibraryFromJarToTemp(final String tmpDir)
            throws IOException {
      final File temp;
      if (tmpDir == null || tmpDir.isEmpty()) {
        temp = File.createTempFile(tempFilePrefix, tempFileSuffix);
      } else {
        temp = new File(tmpDir, jniLibraryFileName);
        if (temp.exists() && !temp.delete()) {
          throw new RuntimeException("File: " + temp.getAbsolutePath()
              + " already exists and cannot be removed.");
        }
        if (!temp.createNewFile()) {
          throw new RuntimeException("File: " + temp.getAbsolutePath()
              + " could not be created.");
        }
      }
  
      if (!temp.exists()) {
        throw new RuntimeException("File " + temp.getAbsolutePath() + " does not exist.");
      } else {
        temp.deleteOnExit();
      }
  
      // attempt to copy the library from the Jar file to the temp destination
      try (final InputStream is = getClass().getClassLoader().
        getResourceAsStream(jniLibraryFileName)) {
        if (is == null) {
          throw new RuntimeException(jniLibraryFileName + " was not found inside JAR.");
        } else {
          Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
        }
      }
  
      return temp;
    }
  
    /**
     * Private constructor to disallow instantiation
     */
    private NativeLibraryLoader() {
    }
  }
  