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 . 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 ; } log . debug ( "resource found @ " + url ) ; if ( url . getProtocol ( ) . equals ( "jar" ) ) { log . debug ( "resource in jar; extracting file if necessary..." ) ; String versionHash = getJarVersionHashForResource ( url ) ; log . debug ( "version hash [" + versionHash + "]" ) ; File d = options . getExtractDir ( ) ; if ( d == null ) { d = getOrCreateTempDirectory ( options . isCleanupExtracted ( ) ) ; } else { if ( ! d . exists ( ) ) { d . mkdirs ( ) ; } if ( ! d . isDirectory ( ) ) { throw new ExtractException ( "Extract dir [" + d + "] is not a directory" ) ; } } log . debug ( "using dir [" + d + "]" ) ; File exeFile = new File ( d , targetFileName ) ; File exeHashFile = new File ( exeFile . getAbsolutePath ( ) + ".hash" ) ; if ( exeFile . exists ( ) ) { log . debug ( "file already exists; verifying if hash matches" ) ; if ( ! exeHashFile . exists ( ) ) { exeFile . delete ( ) ; } else { String existingHash = readFileToString ( exeHashFile ) ; if ( existingHash == null || ! existingHash . equals ( versionHash ) ) { log . debug ( "hash mismatch; deleting files; will freshly extract file" ) ; exeFile . delete ( ) ; exeHashFile . delete ( ) ; } else { log . debug ( "hash matches; will use existing file" ) ; return exeFile ; } } } if ( ! exeFile . exists ( ) ) { try { log . debug ( "extracting [" + url + "] to [" + exeFile + "]..." ) ; extractTo ( url , exeFile ) ; log . debug ( "setting to executable" ) ; exeFile . setExecutable ( true ) ; log . debug ( "writing hash file" ) ; writeStringToFile ( exeHashFile , versionHash ) ; 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