/**
     * Find the GhostDriver main file (i.e. {@code "main.js"}).
     *
     * Looks into the Capabilities and the System Properties for
     * {@link PhantomJSDriverService#PHANTOMJS_GHOSTDRIVER_PATH_PROPERTY}.
     *
     * NOTE: If both the Capability and the System Property are set, the Capability takes priority.
     *
     * @param desiredCapabilities Capabilities in which we will look for the path to GhostDriver
     * @param docsLink            The link to the GhostDriver documentation page
     * @param downloadLink        The link to the GhostDriver download page
     * @return The driver executable as a {@link File} object
     * @throws IllegalStateException If the executable not found or cannot be executed
     */
    protected static File findGhostDriver(Capabilities desiredCapabilities, String docsLink, String downloadLink) {
        // Recover path to GhostDriver from the System Properties or the Capabilities
        String ghostdriverpath;
        if (desiredCapabilities != null &&
                desiredCapabilities.getCapability(PHANTOMJS_GHOSTDRIVER_PATH_PROPERTY) != null) {
            ghostdriverpath = (String) desiredCapabilities.getCapability(PHANTOMJS_GHOSTDRIVER_PATH_PROPERTY);
        } else {
            ghostdriverpath = System.getProperty(PHANTOMJS_GHOSTDRIVER_PATH_PROPERTY);
        }

        if (ghostdriverpath != null) {
            // Check few things on the file before returning it
            File ghostdriver = new File(ghostdriverpath);
            checkState(ghostdriver.exists(),
                    "The GhostDriver does not exist: %s",
                    ghostdriver.getAbsolutePath());
            checkState(ghostdriver.isFile(),
                    "The GhostDriver is a directory: %s",
                    ghostdriver.getAbsolutePath());
            checkState(ghostdriver.canRead(),
                    "The GhostDriver is not a readable file: %s",
                    ghostdriver.getAbsolutePath());

            return ghostdriver;
        }

        // This means that no GhostDriver System Property nor Capability was set
        return null;
    }
  /**
   * Looks into the Capabilities, the current $PATH and the System Properties for {@link
   * PhantomJSDriverService#PHANTOMJS_EXECUTABLE_PATH_PROPERTY}.
   *
   * <p>NOTE: If the Capability, the $PATH and the System Property are set, the Capability takes
   * priority over the System Property, that in turn takes priority over the $PATH.
   *
   * @param desiredCapabilities Capabilities in which we will look for the path to PhantomJS
   * @param docsLink The link to the PhantomJS documentation page
   * @param downloadLink The link to the PhantomJS download page
   * @return The driver executable as a {@link File} object
   * @throws IllegalStateException If the executable not found or cannot be executed
   */
  @SuppressWarnings("deprecation")
  protected static File findPhantomJS(
      Capabilities desiredCapabilities, String docsLink, String downloadLink) {
    String phantomjspath = null;
    if (desiredCapabilities != null
        && desiredCapabilities.getCapability(PHANTOMJS_EXECUTABLE_PATH_PROPERTY) != null) {
      phantomjspath =
          (String) desiredCapabilities.getCapability(PHANTOMJS_EXECUTABLE_PATH_PROPERTY);
    } else {
      phantomjspath = CommandLine.find(PHANTOMJS_DEFAULT_EXECUTABLE);
      phantomjspath = System.getProperty(PHANTOMJS_EXECUTABLE_PATH_PROPERTY, phantomjspath);
    }

    checkState(
        phantomjspath != null,
        "The path to the driver executable must be set by the %s capability/system property/PATH variable;"
            + " for more information, see %s. "
            + "The latest version can be downloaded from %s",
        PHANTOMJS_EXECUTABLE_PATH_PROPERTY,
        docsLink,
        downloadLink);

    File phantomjs = new File(phantomjspath);
    checkExecutable(phantomjs);
    return phantomjs;
  }
 @Override
 public void close() throws BlockStoreException {
   try {
     buffer.force();
     if (System.getProperty("os.name").toLowerCase().contains("win")) {
       log.info("Windows mmap hack: Forcing buffer cleaning");
       WindowsMMapHack.forceRelease(buffer);
     }
     buffer = null; // Allow it to be GCd and the underlying file mapping to go away.
     randomAccessFile.close();
   } catch (IOException e) {
     throw new BlockStoreException(e);
   }
 }
  /**
   * Find the GhostDriver main file (i.e. <code>"main.js"</code>).
   *
   * <p>Looks into the Capabilities and the System Properties for {@link
   * PhantomJSDriverService#PHANTOMJS_GHOSTDRIVER_PATH_PROPERTY}.
   *
   * <p>NOTE: If both the Capability and the System Property are set, the Capability takes priority.
   *
   * @param desiredCapabilities Capabilities in which we will look for the path to GhostDriver
   * @param docsLink The link to the GhostDriver documentation page
   * @param downloadLink The link to the GhostDriver download page
   * @return The driver executable as a {@link File} object
   * @throws IllegalStateException If the executable not found or cannot be executed
   */
  protected static File findGhostDriver(
      Capabilities desiredCapabilities, String docsLink, String downloadLink) {
    // Recover path to GhostDriver from the System Properties or the Capabilities
    String ghostdriverpath = null;
    if (desiredCapabilities != null
        && (String) desiredCapabilities.getCapability(PHANTOMJS_GHOSTDRIVER_PATH_PROPERTY)
            != null) {
      ghostdriverpath =
          (String) desiredCapabilities.getCapability(PHANTOMJS_GHOSTDRIVER_PATH_PROPERTY);
    } else {
      ghostdriverpath = System.getProperty(PHANTOMJS_GHOSTDRIVER_PATH_PROPERTY, ghostdriverpath);
    }

    if (ghostdriverpath != null) {
      checkState(
          ghostdriverpath != null,
          "The path to the driver executable must be set by the '%s' capability/system property;"
              + " for more information, see %s. "
              + "The latest version can be downloaded from %s",
          PHANTOMJS_GHOSTDRIVER_PATH_PROPERTY,
          docsLink,
          downloadLink);

      // Check few things on the file before returning it
      File ghostdriver = new File(ghostdriverpath);
      checkState(
          ghostdriver.exists(),
          "The GhostDriver does not exist: %s",
          ghostdriver.getAbsolutePath());
      checkState(
          ghostdriver.isFile(),
          "The GhostDriver is a directory: %s",
          ghostdriver.getAbsolutePath());
      checkState(
          ghostdriver.canRead(),
          "The GhostDriver is not a readable file: %s",
          ghostdriver.getAbsolutePath());

      return ghostdriver;
    }

    // This means that no GhostDriver System Property nor Capability was set
    return null;
  }