src/main/java/com/fizzed/jne/JNE.java
synchronized static public File find(String fileName, String targetFileName, Options options, OperatingSystem os, HardwareArchitecture arch) throws IOException {
        if (options == null) {
            options = DEFAULT_OPTIONS;
        }

        if (os == null || os == OperatingSystem.UNKNOWN) {
            throw new ExtractException("Unable to detect operating system (e.g. Windows)");
        }

        if (arch == null || arch == HardwareArchitecture.UNKNOWN) {
            throw new ExtractException("Unable to detect hardware architecture (e.g. x86)");
        }

        if (targetFileName == null) {
            targetFileName = fileName;
        }

        log.debug("finding fileName [" + fileName + "] targetFileName [" + targetFileName + "] os [" + os + "] arch [" + arch + "]...");

        //String resourcePath = options.getResourcePrefix() + "/" + os.name().toLowerCase() + "/" + arch.name().toLowerCase() + "/" + name;
        String resourcePath = options.createResourcePath(os, arch, fileName);

        log.debug("finding resource [" + resourcePath + "]");

        URL url = JNE.class.getResource(resourcePath);
        if (url == null) {
            log.debug("resource [" + resourcePath + "] not found");
            return null;
        }

        // support for "file" and "jar"
        log.debug("resource found @ " + url);

        if (url.getProtocol().equals("jar")) {
            log.debug("resource in jar; extracting file if necessary...");

            // in the case of where the app specifies an extract directory and
            // does not request deleteOnExit we need a way to detect if the 
            // executables changed from the previous app run -- we do this with
            // a very basic "hash" for an extracted resource. We basically combine
            // the path of the jar and manifest version of when the exe was extracted
            String versionHash = getJarVersionHashForResource(url);
            log.debug("version hash [" + versionHash + "]");

            // where should we extract the executable?
            File d = options.getExtractDir();
            if (d == null) {
                d = getOrCreateTempDirectory(options.isCleanupExtracted());
            } else {
                // does the extract dir exist?
                if (!d.exists()) {
                    d.mkdirs();
                }
                if (!d.isDirectory()) {
                    throw new ExtractException("Extract dir [" + d + "] is not a directory");
                }
            }

            log.debug("using dir [" + d + "]");

            // create both target exe and hash files
            File exeFile = new File(d, targetFileName);
            File exeHashFile = new File(exeFile.getAbsolutePath() + ".hash");

            // if file already exists verify its hash
            if (exeFile.exists()) {
                log.debug("file already exists; verifying if hash matches");
                // verify the version hash still matches
                if (!exeHashFile.exists()) {
                    // hash file missing -- we will force a new extract to be safe
                    exeFile.delete();
                } else {
                    // hash file exists, verify it matches what we expect
                    String existingHash = readFileToString(exeHashFile);
                    if (existingHash == null || !existingHash.equals(versionHash)) {
                        log.debug("hash mismatch; deleting files; will freshly extract file");
                        // hash mismatch -- will force an overwrite of both files
                        exeFile.delete();
                        exeHashFile.delete();
                    } else {
                        log.debug("hash matches; will use existing file");
                        // hash match (exeFile and exeHashFile are both perrrrfect)
                        //System.out.println("exe already extracted AND hash matched -- reusing same exe");
                        return exeFile;
                    }
                }
            }

            // does exe already exist? (previously extracted)
            if (!exeFile.exists()) {
                try {
                    log.debug("extracting [" + url + "] to [" + exeFile + "]...");
                    extractTo(url, exeFile);

                    // set file to "executable"
                    log.debug("setting to executable");
                    exeFile.setExecutable(true);

                    // create corrosponding hash file
                    log.debug("writing hash file");
                    writeStringToFile(exeHashFile, versionHash);

                    // schedule files for deletion?
                    if (options.isCleanupExtracted()) {
                        log.debug("scheduling file and hash for delete on exit");
                        exeFile.deleteOnExit();
                        exeHashFile.deleteOnExit();
                    }
                } catch (IOException e) {
                    log.debug("failed to extract file");
                    throw new ExtractException("Unable to cleanly extract executable from jar", e);
                }
            }

            log.debug("returning [" + exeFile + "]");
            return exeFile;
        } else if (url.getProtocol().equals("file")) {
            log.debug("resource in file");
            try {
                File exeFile = new File(url.toURI());
                if (!exeFile.canExecute()) {
                    log.debug("setting file to executable");
                    if (!exeFile.setExecutable(true)) {
                        log.debug("unable to cleanly set file to executable");
                        throw new ExtractException("Executable was found but it cannot be set to execute [" + exeFile.getAbsolutePath() + "]");
                    }
                }
                log.debug("returning [" + exeFile + "]");
                return exeFile;
            } catch (URISyntaxException e) {
                log.debug("uri syntax error");
                throw new ExtractException("Unable to create executable file from uri", e);
            }
        } else {
            throw new ExtractException("Unsupported executable resource protocol [" + url.getProtocol() + "]");
        }
    }
synchronized static public File find(String fileName, String targetFileName, Options options, OperatingSystem os, HardwareArchitecture arch) throws IOException {
        if (options == null) {
            options = DEFAULT_OPTIONS;
        }

        if (os == null || os == OperatingSystem.UNKNOWN) {
            throw new ExtractException("Unable to detect operating system (e.g. Windows)");
        }

        if (arch == null || arch == HardwareArchitecture.UNKNOWN) {
            throw new ExtractException("Unable to detect hardware architecture (e.g. x86)");
        }

        if (targetFileName == null) {
            targetFileName = fileName;
        }

        log.debug("finding fileName [" + fileName + "] targetFileName [" + targetFileName + "] os [" + os + "] arch [" + arch + "]...");

        //String resourcePath = options.getResourcePrefix() + "/" + os.name().toLowerCase() + "/" + arch.name().toLowerCase() + "/" + name;
        String resourcePath = options.createResourcePath(os, arch, fileName);

        log.debug("finding resource [" + resourcePath + "]");

        URL url = JNE.class.getResource(resourcePath);
        if (url == null) {
            log.debug("resource [" + resourcePath + "] not found");
            return null;
        }

        // support for "file" and "jar"
        log.debug("resource found @ " + url);

        if (url.getProtocol().equals("jar")) {
            log.debug("resource in jar; extracting file if necessary...");

            // in the case of where the app specifies an extract directory and
            // does not request deleteOnExit we need a way to detect if the 
            // executables changed from the previous app run -- we do this with
            // a very basic "hash" for an extracted resource. We basically combine
            // the path of the jar and manifest version of when the exe was extracted
            String versionHash = getJarVersionHashForResource(url);
            log.debug("version hash [" + versionHash + "]");

            // where should we extract the executable?
            File d = options.getExtractDir();
            if (d == null) {
                d = getOrCreateTempDirectory(options.isCleanupExtracted());
            } else {
                // does the extract dir exist?
                if (!d.exists()) {
                    d.mkdirs();
                }
                if (!d.isDirectory()) {
                    throw new ExtractException("Extract dir [" + d + "] is not a directory");
                }
            }

            log.debug("using dir [" + d + "]");

            // create both target exe and hash files
            File exeFile = new File(d, targetFileName);
            File exeHashFile = new File(exeFile.getAbsolutePath() + ".hash");

            // if file already exists verify its hash
            if (exeFile.exists()) {
                log.debug("file already exists; verifying if hash matches");
                // verify the version hash still matches
                if (!exeHashFile.exists()) {
                    // hash file missing -- we will force a new extract to be safe
                    exeFile.delete();
                } else {
                    // hash file exists, verify it matches what we expect
                    String existingHash = readFileToString(exeHashFile);
                    if (existingHash == null || !existingHash.equals(versionHash)) {
                        log.debug("hash mismatch; deleting files; will freshly extract file");
                        // hash mismatch -- will force an overwrite of both files
                        exeFile.delete();
                        exeHashFile.delete();
                    } else {
                        log.debug("hash matches; will use existing file");
                        // hash match (exeFile and exeHashFile are both perrrrfect)
                        //System.out.println("exe already extracted AND hash matched -- reusing same exe");
                        return exeFile;
                    }
                }
            }

            // does exe already exist? (previously extracted)
            if (!exeFile.exists()) {
                try {
                    log.debug("extracting [" + url + "] to [" + exeFile + "]...");
                    extractTo(url, exeFile);

                    // set file to "executable"
                    log.debug("setting to executable");
                    exeFile.setExecutable(true);

                    // create corrosponding hash file
                    log.debug("writing hash file");
                    writeStringToFile(exeHashFile, versionHash);

                    // schedule files for deletion?
                    if (options.isCleanupExtracted()) {
                        log.debug("scheduling file and hash for delete on exit");
                        exeFile.deleteOnExit();
                        exeHashFile.deleteOnExit();
                    }
                } catch (IOException e) {
                    log.debug("failed to extract file");
                    throw new ExtractException("Unable to cleanly extract executable from jar", e);
                }
            }

            log.debug("returning [" + exeFile + "]");
            return exeFile;
        } else if (url.getProtocol().equals("file")) {
            log.debug("resource in file");
            try {
                File exeFile = new File(url.toURI());
                if (!exeFile.canExecute()) {
                    log.debug("setting file to executable");
                    if (!exeFile.setExecutable(true)) {
                        log.debug("unable to cleanly set file to executable");
                        throw new ExtractException("Executable was found but it cannot be set to execute [" + exeFile.getAbsolutePath() + "]");
                    }
                }
                log.debug("returning [" + exeFile + "]");
                return exeFile;
            } catch (URISyntaxException e) {
                log.debug("uri syntax error");
                throw new ExtractException("Unable to create executable file from uri", e);
            }
        } else {
            throw new ExtractException("Unsupported executable resource protocol [" + url.getProtocol() + "]");
        }
    }
Underlying method used by findExecutable and loadLibrary to find and
extract executables as needed. Although public, it's NOT recommended to
use this method unless you know what you're doing.

@param fileName
@param targetFileName
@param options
@param os
@param arch
@return
@throws IOException
@throws ExtractException