/* * Copyright 2010-2016, Sikuli.org, sikulix.com * Released under the MIT License. * * modified RaiMan 2014 */ package org.sikuli.basics; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.lang.reflect.Field; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.security.CodeSource; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.StringTokenizer; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.sikuli.script.RunTime; //import org.sikuli.script.RunTime; import org.sikuli.script.Sikulix; public class ResourceLoader { private static ResourceLoader resourceLoader = null; //<editor-fold defaultstate="collapsed" desc="new logging concept"> private static String me = "ResourceLoader"; private static String mem = "..."; private static int lvl = 3; private static void log(int level, String message, Object... args) { Debug.logx(level, me + ": " + mem + ": " + message, args); } private static void log0(int level, String message, Object... args) { Debug.logx(level, me + ": " + message, args); } //</editor-fold> private final String loaderName = "basic"; private static final String NL = String.format("%n"); private StringBuffer alreadyLoaded = new StringBuffer(""); private ClassLoader cl; private CodeSource codeSrc; private String jarParentPath = null; private String jarPath = null; private URL apiJarURL = null; private URL jarURL = null; private URL libsURL = null; private URL tessURL = null; private URL currentURL; private String fileList = "/filelist.txt"; private static final String sikhomeEnv = System.getenv("SIKULIX_HOME"); private static final String sikhomeProp = System.getProperty("sikuli.Home"); private static final String userdir = System.getProperty("user.dir"); private static final String userhome = System.getProperty("user.home"); private String libPath = null; private String libPathFallBack = null; private File libsDir = null; // private static final String checkFileNameAll = RunTime.get().getVersionShortBasic() + "-MadeForSikuliX"; // private final String checkFileNameMac = checkFileNameAll + "64M.txt"; // private final String checkFileNameW32 = checkFileNameAll + "32W.txt"; // private final String checkFileNameW64 = checkFileNameAll + "64W.txt"; // private final String checkFileNameL32 = checkFileNameAll + "32L.txt"; // private final String checkFileNameL64 = checkFileNameAll + "64L.txt"; private String checkFileName = null; private String checkLib = null; private final String checkLibWindows = "JIntellitype"; private static final String prefixSikuli = "SikuliX"; private static final String suffixLibs = "libs"; private static final String libSub = prefixSikuli + "/" + suffixLibs; private String userSikuli = null; public boolean extractingFromJar = false; private boolean runningSikulixapi = false; private static boolean itIsJython = false; /** * Mac: standard place for native libs */ private static final String libPathMac = Settings.appPathMac + "/libs"; /** * in-jar folder to load other ressources from */ private static final String jarResources = "META-INF/res/"; /** * in-jar folder to load native libs from */ private static final String libSourcebase = "META-INF/libs/"; private static final String libSource32 = libSourcebase + "%s/libs32/"; private static final String libSource64 = libSourcebase + "%s/libs64/"; private String libSource; private String osarch; private String javahome; private boolean initDone = false; private boolean usrPathProblem = false; private ResourceLoader() { // log0(lvl, "SikuliX Package Build: %s %s", RunTime.get().getVersionShort(), RunTime.get().SikuliVersionBuild); cl = this.getClass().getClassLoader(); codeSrc = this.getClass().getProtectionDomain().getCodeSource(); if (codeSrc != null && codeSrc.getLocation() != null) { jarURL = codeSrc.getLocation(); jarPath = jarURL.getPath(); jarParentPath = FileManager.slashify((new File(jarPath)).getParent(), true); if (jarPath.endsWith(".jar")) { //TODO evaluation of running situation should be put in one place extractingFromJar = true; if (jarPath.contains("sikulixapi")) { runningSikulixapi = true; org.sikuli.script.Sikulix.setRunningSikulixapi(true); } } else { jarPath = FileManager.slashify((new File(jarPath)).getAbsolutePath(), true); } if (Settings.isMac()) { if (jarParentPath.startsWith(Settings.appPathMac)) { log0(lvl, "Sikuli-IDE is running from /Applications folder"); Settings.isMacApp = true; } } } else { log(-1, "Fatal Error 101: Not possible to access the jar files!"); Sikulix.terminate(101); } } public static ResourceLoader get() { if (resourceLoader == null) { resourceLoader = new ResourceLoader(); } return resourceLoader; } //<editor-fold defaultstate="collapsed" desc="obsolete"> //public static ResourceLoader forJar(String jarName) { // ResourceLoader rl = get(); // URL jar = null; // if (new File(jarName).isAbsolute()) { // try { // jar = new URL("file", null, jarName); // } catch (MalformedURLException ex) { // log(-1, "%s", ex); // } // } else { // jar = getJarFromClasspath(jarName); // } // if (jar != null) { // rl.setCurrentJar(jar); // return rl; // } else { // return null; // } // } // private static URL getJarFromClasspath(String jarName) { // URLClassLoader sysLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); // URL[] urls = sysLoader.getURLs(); // URL jarurl = null; // for (URL url : urls) { // if (url.getPath().toLowerCase().contains(jarName)) { // jarurl = url; // break; // } // } // return jarurl; // } // // private void setCurrentJar(URL jar) { // currentURL = jar; // } //</editor-fold> public URL setApiJarURL(String pURL) { apiJarURL = null; try { apiJarURL = (new URI("file", pURL, null)).toURL(); } catch (Exception ex) { } return apiJarURL; } //<editor-fold defaultstate="collapsed" desc="now implemented in RunTime"> // public boolean check(String what) { // mem = "check"; // // if (!what.equals(Settings.SIKULI_LIB)) { // log(-1, "Currently only Sikuli libs supported!"); // return false; // } // // if (initDone) { // return true; // } // // if (libPath == null || libsDir == null) { // libPath = null; // libsDir = null; // File libsfolder; // String libspath; // // if (System.getProperty("sikuli.DoNotExport") == null && !isFatJar() && !Settings.isWinApp) { // libsURL = null; ////TODO evaluation of running situation should be put in one place // String jarName = ""; // String libsJarName = ""; // String tessJarName = ""; // if (apiJarURL != null) { // libsURL = apiJarURL; // } else { // if (jarPath.contains("API")) { // log(-1, "The jar in use was not built with setup!\n" // + "We might be running from local Maven repository?\n" + jarPath); // jarName = "API"; // libsJarName = "Libs" + Settings.getShortOS(); // tessJarName = "Tesseract"; // } // if (runningSikulixapi) { // log(3, "The jar in use is some sikulixapi.jar\n%s", jarPath); // libsJarName = "sikulixlibs" + Settings.getShortOS(); // jarName = "sikulixapi"; // tessJarName = "sikulixtessdata"; // } // if (!jarName.isEmpty()) { // try { // libsURL = new URL(jarURL.toString().replace(jarName, libsJarName)); // if (!Sikulix.addToClasspath(libsURL.getPath()) // || !org.sikuli.script.Sikulix.isOnClasspath(libsJarName)) { // libsURL = null; // } // } catch (Exception ex) { // log(-1, "\n%s", ex); // } // } // } // if (libsURL == null) { // log(-1, "Terminating: The jar was not built with setup nor " // + "can the libs be exported from classpath!\n" + jarPath); // Sikulix.terminate(999); // } // } // // // check the bit-arch // osarch = System.getProperty("os.arch"); // log(lvl - 1, "we are running on arch: " + osarch); // javahome = FileManager.slashify(System.getProperty("java.home"), true); // log(lvl - 1, "using Java at: " + javahome); // // if (userhome != null) { // if (Settings.isWindows()) { // userSikuli = System.getenv("USERPROFILE"); // if (userSikuli != null) { // userSikuli = FileManager.slashify(userSikuli, true) + prefixSikuli; // } // } else { // userSikuli = FileManager.slashify(userhome, true) + prefixSikuli; // } // } // // // Mac specific // if (Settings.isMac()) { // if (!osarch.contains("64")) { // log(-1, "Mac: only 64-Bit supported"); // Sikulix.terminate(999); // } // libSource = String.format(libSource64, "mac"); // checkFileName = checkFileNameMac; // checkLib = "VisionProxy"; ////TODO libs dir fallback //// if ((new File(libPathMac)).exists()) { //// libPathFallBack = libPathMac; //// } // } // // // Windows specific // if (Settings.isWindows()) { // if (osarch.contains("64")) { // libSource = String.format(libSource64, "windows"); // checkFileName = checkFileNameW64; ////TODO libs dir fallback //// if ((new File(libPathWin)).exists()) { //// libPathFallBack = libPathWin; //// } // } else { // libSource = String.format(libSource32, "windows"); // checkFileName = checkFileNameW32; ////TODO libs dir fallback //// if ((new File(libPathWin)).exists()) { //// libPathFallBack = libPathWin; //// } else if ((new File(libPathWin32)).exists()) { //// libPathFallBack = libPathWin32; //// } // } // checkLib = "VisionProxy"; // } // // // Linux specific // if (Settings.isLinux()) { // if (osarch.contains("64")) { // libSource = String.format(libSource64, "linux"); // checkFileName = checkFileNameL64; // } else { // libSource = String.format(libSource32, "linux"); // checkFileName = checkFileNameL32; // } // checkLib = "VisionProxy"; // } // // if (!Settings.isWinApp && !Settings.runningSetup) { // // check Java property sikuli.home // if (sikhomeProp != null) { // libspath = FileManager.slashify(sikhomeProp, true) + "libs"; // if ((new File(libspath)).exists()) { // libPath = libspath; // } // log(lvl, "Exists Property.sikuli.Home? %s: %s", libPath == null ? "NO" : "YES", libspath); // libsDir = checkLibsDir(libPath); // } // // // check environmenet SIKULIX_HOME // if (libPath == null && sikhomeEnv != null) { // libspath = FileManager.slashify(sikhomeEnv, true) + "libs"; // if ((new File(libspath)).exists()) { // libPath = libspath; // } // log(lvl, "Exists Environment.SIKULIX_HOME? %s: %s", libPath == null ? "NO" : "YES", libspath); // libsDir = checkLibsDir(libPath); // } // // // check parent folder of jar file // if (libPath == null && jarPath != null) { // if (extractingFromJar) { // if (libsURL == null || runningSikulixapi) { // if (Settings.isMacApp) { // libsfolder = new File(libPathMac); // } else { // libsfolder = (new File(jarParentPath, "libs")); // } // if (libsfolder.exists()) { // libPath = libsfolder.getAbsolutePath(); // } else if (runningSikulixapi) { // if (!libsfolder.mkdirs()) { // log(-1, "running some sikulixapi.jar: cannot create libs folder in\n%s", jarParentPath); // } else { // libPath = libsfolder.getAbsolutePath(); // } // } // log(lvl, "Exists libs folder at location of jar? %s: %s", libPath == null ? "NO" : "YES", jarParentPath); // libsDir = checkLibsDir(libPath); // if (libsDir == null) { // if (System.getProperty("sikuli.DoNotExport") != null) { // log(-1, "No valid libs folder with option sikuli.DoNotExport"); // System.exit(1); // } // } // } // } else { // log(lvl, "not running from jar: " + jarParentPath); // } // } // // // check the users home folder // if (!Settings.runningSetup && !runningSikulixapi && libPath == null && userSikuli != null) { // File ud = new File(userSikuli, suffixLibs); // if (ud.exists()) { // libPath = ud.getAbsolutePath(); // } // log(lvl, "Exists libs folder in user home folder? %s: %s", libPath == null ? "NO" : "YES", // ud.getAbsolutePath()); // libsDir = checkLibsDir(libPath); // } // // // check the working directory and its parent // if (!Settings.runningSetup && !runningSikulixapi && libPath == null && userdir != null) { // File wd = new File(userdir); // File wdpl = null; // File wdp = new File(userdir).getParentFile(); // File wdl = new File(FileManager.slashify(wd.getAbsolutePath(), true) + libSub); // if (wdp != null) { // wdpl = new File(FileManager.slashify(wdp.getAbsolutePath(), true) + libSub); // } // if (wdl.exists()) { // libPath = wdl.getAbsolutePath(); // } else if (wdpl != null && wdpl.exists()) { // libPath = wdpl.getAbsolutePath(); // } // log(lvl, "Exists libs folder in working folder or its parent? %s: %s", libPath == null ? "NO" : "YES", // wd.getAbsolutePath()); // libsDir = checkLibsDir(libPath); // } // // if (!Settings.runningSetup && !runningSikulixapi && libPath == null && libPathFallBack != null) { // libPath = libPathFallBack; // log(lvl, "Checking available fallback for libs folder: " + libPath); // libsDir = checkLibsDir(libPath); // } // } // } // // if (libsDir == null && libPath != null) { // log(lvl, "libs dir is empty, has wrong content or is outdated"); // log(lvl, "Trying to extract libs to: " + libPath); // if (!FileManager.deleteFileOrFolder(libPath, // new FileManager.FileFilter() { // @Override // public boolean accept(File entry) { // if (entry.getPath().contains("tessdata")) { // return false; // } // return true; // } // })) { // log(-1, "Fatal Error 102: not possible to empty libs dir"); // Sikulix.terminate(102); // } // File dir = (new File(libPath)); // dir.mkdirs(); // if (extractLibs(dir.getParent(), libSource) == null) { // log(-1, "... not possible!"); // libPath = null; // } else { // libsDir = checkLibsDir(libPath); // } // } // // //<editor-fold defaultstate="collapsed" desc="libs dir finally invalid"> // if (libPath == null && !Settings.isWinApp) { // log(-1, "No valid libs path available until now!"); // File jarPathLibs = null; // // if (libPath == null && jarParentPath != null) { // if ((jarPath.endsWith(".jar") && libsURL == null) || apiJarURL != null) { // log(-2, "Please wait! Trying to extract libs to jar parent folder: \n" + jarParentPath); // jarPathLibs = extractLibs((new File(jarParentPath)).getAbsolutePath(), libSource); // if (jarPathLibs == null) { // log(-1, "not possible!"); // } else { // libPath = jarPathLibs.getAbsolutePath(); // } // } else if (Settings.runningSetupInValidContext) { // log(-2, "Please wait! Trying to extract libs to working folder: \n" + jarParentPath); // jarPathLibs = extractLibs(Settings.runningSetupInContext, libSource); // if (jarPathLibs == null) { // log(-1, "not possible!"); // } else { // libPath = jarPathLibs.getAbsolutePath(); // } // } // } // if (libPath == null && userSikuli != null) { // log(-2, "Please wait! Trying to extract libs to user home: \n" + userSikuli); // File userhomeLibs = extractLibs((new File(userSikuli)).getAbsolutePath(), libSource); // if (userhomeLibs == null) { // log(-1, "not possible!"); // } else { // libPath = userhomeLibs.getAbsolutePath(); // } // } // libsDir = checkLibsDir(libPath); // if (libPath == null || libsDir == null) { // log(-1, "Fatal Error 103: No valid native libraries folder available - giving up!"); // Sikulix.terminate(103); // } // } // //</editor-fold> // // if (Settings.isWinApp) { // String osArchNum = osarch.contains("64") ? "64" : "32"; // log(lvl, "isWinApp: checking libs folder"); // String jarLibs = "META-INF/libs/windows/libs" + osArchNum + "/"; // String fContent = jarLibs + "sikulixfoldercontent"; // String sContent = FileManager.extractResourceAsLines(fContent); // File fpLibsWin = new File(Settings.getInstallBase(), "libs"); // log(lvl, "isWinApp: creating libs folder at: \n%s", fpLibsWin); // boolean success = true; // for (String fName : sContent.split("\\n")) { // log(lvl + 1, "libs export: %s", fName); // success &= FileManager.extractResource(jarLibs + fName, new File(fpLibsWin, fName)); // } // if (!success) { // log(-1, "isWinApp: problems creating libs folder"); // Sikulix.terminate(999); // } // libPath = fpLibsWin.getAbsolutePath(); // libsDir = checkLibsDir(libPath); // if (libsDir == null) { // log(-1, "isWinApp: finally giving up"); // Sikulix.terminate(999); // } // } // // if (Settings.isLinux()) { // File libsLinux = new File(libsDir.getParent(), "libsLinux/libVisionProxy.so"); // if (libsLinux.exists()) { // log(lvl, "Trying to use provided library at: " + libsLinux.getAbsolutePath()); // try { // FileManager.xcopy(libsLinux.getAbsolutePath(), // new File(libPath, "libVisionProxy.so").getAbsolutePath()); // } catch (IOException ex) { // log(-1, "... did not work: " + ex.getMessage()); // Sikulix.terminate(999); // } // } // } // //// if (itIsJython) { //// export("Lib/sikuli", libsDir.getParent()); //// itIsJython = false; //// } // if (Settings.OcrDataPath == null && System.getProperty("sikuli.DoNotExport") == null) { // if (Settings.isWindows() || Settings.isMac()) { // Settings.OcrDataPath = libPath; // } else { // Settings.OcrDataPath = "/usr/local/share"; // } // } // // initDone = true; // return libsDir != null; // } // private File checkLibsDir(String path) { // String memx = mem; // mem = "checkLibsDir"; // File dir = null; // if (path != null) { // log(lvl, "trying: " + path); // if (Settings.isWindows() && !initDone) { // log(lvl, "Running on Windows - checking system path!"); // String syspath = SysJNA.WinKernel32.getEnvironmentVariable("PATH"); // if (syspath == null) { // Sikulix.terminate(999); // } else { // path = (new File(path).getAbsolutePath()).replaceAll("/", "\\"); // if (!syspath.toUpperCase().contains(path.toUpperCase())) { // if (!SysJNA.WinKernel32.setEnvironmentVariable("PATH", path + ";" + syspath)) { // Sikulix.terminate(999); // } // log(lvl, "Added libs dir to path: " + path); // syspath = SysJNA.WinKernel32.getEnvironmentVariable("PATH"); // if (!syspath.toUpperCase().contains(path.toUpperCase())) { // log(-1, "Adding to path did not work:\n%s", syspath); // Sikulix.terminate(999); // } // log(lvl, syspath.substring(0, Math.min(path.length()+50, syspath.length())) + "..."); // } // } // if (!checkJavaUsrPath()) { // usrPathProblem = true; // } // } // if (System.getProperty("sikuli.DoNotExport") != null) { // dir = new File(path); // } else { // File checkFile = (new File(FileManager.slashify(path, true) + checkFileName)); // if (checkFile.exists()) { // if ((new File(jarPath)).lastModified() > checkFile.lastModified()) { // log(lvl + 1, "libs folder outdated!"); // } else { // //convenience: jawt.dll in libsdir avoids need for java/bin in system path // if (Settings.isWindows()) { // String lib = "jawt.dll"; // try { // extractResource(javahome + "bin/" + lib, new File(libPath, lib), false); // log(lvl + 1, "copied to libs: jawt.dll"); // } catch (IOException ex) { // log(-1, "Fatal error 107: problem copying " + lib + "\n" + ex.getMessage()); // Sikulix.terminate(107); // } // } // loadLib(checkLib); // log(lvl, "Using libs at: " + path); // dir = new File(path); // } // } else { // if (Settings.isWindows()) { // // might be wrong arch // if ((new File(FileManager.slashify(path, true) + checkFileNameW32)).exists() // || (new File(FileManager.slashify(path, true) + checkFileNameW64)).exists()) { // log(lvl + 1, "libs dir contains wrong arch for " + osarch); // } // } else { // log(-1, "Not a valid libs dir for SikuliX (" + osarch + "): " + path); // } // } // } // } // mem = memx; // return dir; // } // private boolean checkJavaUsrPath() { // if (Settings.isWindows() && libPath != null) { // log(lvl, "checking ClassLoader.usrPaths having: %s", libPath); // Field usrPathsField = null; // try { // usrPathsField = ClassLoader.class.getDeclaredField("usr_paths"); // } catch (NoSuchFieldException ex) { // log(-1, ex.getMessage()); // } catch (SecurityException ex) { // log(-1, ex.getMessage()); // } // boolean contained = false; // if (usrPathsField != null) { // usrPathsField.setAccessible(true); // try { // //get array of paths // String[] javapaths = (String[]) usrPathsField.get(null); // //check if the path to add is already present // for (String p : javapaths) { // if (FileManager.pathEquals(p, libPath)) { // contained = true; // break; // } // } // //add the new path // if (!contained) { // final String[] newPaths = Arrays.copyOf(javapaths, javapaths.length + 1); // newPaths[newPaths.length - 1] = libPath; // usrPathsField.set(null, newPaths); // log(lvl, "added to ClassLoader.usrPaths"); // } // } catch (IllegalAccessException ex) { // log(-1, ex.getMessage()); // } catch (IllegalArgumentException ex) { // log(-1, ex.getMessage()); // } // return true; //// //check the new path //// if (!contained) { //// try { //// System.loadLibrary(checkLibWindows); //// } catch (java.lang.UnsatisfiedLinkError ex) { //// log(-1, "adding to ClassLoader.usrPaths did not work:\n" + ex.getMessage()); //// System.exit(1); //// } //// } // } // } // return false; // } // // private boolean isFatJar() { // if (extractingFromJar) { // try { // ZipInputStream zip = new ZipInputStream(jarURL.openStream()); // ZipEntry ze; // while ((ze = zip.getNextEntry()) != null) { // String entryName = ze.getName(); // if (entryName.startsWith(libSourcebase)) { // return true; // } // } // } catch (IOException e) { // return false; // } // } // return false; // } // // public File getLibsDir() { // return libsDir; // } //</editor-fold> public boolean export(URL fromURL, String res, String targetPath) { currentURL = fromURL; boolean success = export(res, targetPath); currentURL = null; return success; } /** * @param res what to export * @param targetPath target folder * @return success */ public boolean export(String res, String targetPath) { String memx = mem; mem = "export"; log(lvl, "Trying to access package for exporting: %s to:\n%s", res, targetPath); boolean fastReturn = false; String pre = null, suf = "", tok = res; String[] parts; if (res.indexOf("#") != -1) { tok = res.replace("#", "/"); if (tok.startsWith("/")) { tok = tok.substring(1); } parts = res.split("#"); if (parts.length > 2) { log(-1, "export: invalid resource: %s", res); return false; } if (parts.length > 1) { if (!parts[0].isEmpty()) { pre = parts[0]; suf = parts[1]; } else if (!parts[1].isEmpty()) { pre = ""; suf = parts[1]; } } else { pre = tok; } fastReturn = true; log(lvl, "export with #: %s (%s)-(%s) as %s", res, pre, suf, tok); } if (currentURL == null) { currentURL = jarURL; } extractingFromJar = currentURL.getPath().endsWith(".jar"); List<String[]> entries = makePackageFileList(currentURL, tok, true); if (entries == null || entries.isEmpty()) { return false; } String targetName = null, source = null; File targetFile; long targetDate, entryDate; for (String[] e : entries) { try { entryDate = Long.valueOf(e[1]); source = e[0]; if (pre != null) { parts = source.split(tok); if (parts.length == 2) { targetName = suf + parts[1]; } else { targetName = suf; } targetFile = new File(targetPath, targetName); } else { targetFile = new File(targetPath, source); } if (targetFile.exists()) { targetDate = targetFile.lastModified(); } else { targetDate = 0; targetFile.getParentFile().mkdirs(); } if (targetDate == 0 || targetDate < entryDate) { extractResource(source, targetFile, extractingFromJar); log(lvl + 1, "is dated: %s (%d)", entryDate, targetDate); } else { log(lvl + 1, "already in place: " + targetName); if (fastReturn) { return true; } } } catch (IOException ex) { log(-1, "IO-problem extracting: %s\n%s", targetName, ex.getMessage()); mem = memx; return false; } } return true; } public void setItIsJython() { itIsJython = true; } public String runcmd(String cmd) { return runcmd(new String[]{cmd}); } public String runcmd(String args[]) { return RunTime.get().runcmd(args); //<editor-fold defaultstate="collapsed" desc="obsolete"> // if (args.length == 0) { // return ""; // } // if (args.length == 1) { // String separator = "\""; // ArrayList<String> argsx = new ArrayList<String>(); // StringTokenizer toks; // String tok; // String cmd = args[0]; // if (Settings.isWindows()) { // cmd = cmd.replaceAll("\\\\ ", "%20;"); // } // toks = new StringTokenizer(cmd); // while (toks.hasMoreTokens()) { // tok = toks.nextToken(" "); // if (tok.length() == 0) { // continue; // } // if (separator.equals(tok)) { // continue; // } // if (tok.startsWith(separator)) { // if (tok.endsWith(separator)) { // tok = tok.substring(1, tok.length() - 1); // } else { // tok = tok.substring(1); // tok += toks.nextToken(separator); // } // } // argsx.add(tok.replaceAll("%20;", " ")); // } // args = argsx.toArray(new String[0]); // } // if (args[0].startsWith("#")) { // String pgm = args[0].substring(1); // args[0] = (new File(libsDir, pgm)).getAbsolutePath(); // runcmd(new String[]{"chmod", "ugo+x", args[0]}); // } // String memx = mem; // mem = "runcmd"; // String result = ""; // String error = "*** error ***" + NL; // try { // if (lvl <= Debug.getDebugLevel()) { // log(lvl, Sikulix.arrayToString(args)); // } else { // Debug.info("runcmd: " + Sikulix.arrayToString(args)); // } // Process process = Runtime.getRuntime().exec(args); // BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream())); // BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream())); // String s; // while ((s = stdInput.readLine()) != null) { // if (!s.isEmpty()) { // result += s + NL; // } // } // if ((s = stdError.readLine()) != null) { // result = error + result; // result += s; // } // } catch (Exception e) { // log(-1, "fatal error: " + e.getMessage()); // result = error + e.getMessage(); // } // mem = memx; // return result; //</editor-fold> } /** * make sure, a native library is available and loaded * * @param libname System.loadLibrary() compatible library name */ public void loadLib(String libname) { String memx = mem; mem = "loadLib"; if (libname == null || "".equals(libname)) { log(-1, "libname == null"); mem = memx; return; } if (alreadyLoaded.indexOf("*" + libname) < 0) { alreadyLoaded.append("*").append(libname); } else { log(lvl + 1, "Is already loaded: " + libname); mem = memx; return; } log(lvl + 1, libname); if (libPath == null) { log(-1, "Fatal Error 108: No libs directory available"); Sikulix.terminate(108); } String mappedlib = System.mapLibraryName(libname); if (Settings.isMac()) { if (mappedlib.endsWith(".jnilib")) { mappedlib = mappedlib.replace(".jnilib", ".dylib"); } } String lib = new File(libPath, mappedlib).getAbsolutePath(); if (!new File(lib).exists()) { if (!Settings.isLinux()) { log(-1, "Fatal Error 109: not found: " + lib); Sikulix.terminate(109); } else { lib = mappedlib; log(lvl, "Linux: %s \nnot bundled - trying to load from system paths", lib); //TODO try to find it on LD_LIBRARY_PATH Sikulix.terminate(109); } } else { log(lvl + 1, "Found: " + libname + " at " + lib); } try { System.load(lib); } catch (Error e) { log(-1, "Fatal Error 110: loading: " + mappedlib); log(-1, "Since native library was found at %s\n it might be a problem with needed dependent libraries\nERROR: %s", libPath, e.getMessage()); if (Settings.isWindows()) { log(-1, "Check, wether a valid Sikuli libs folder is in system path at runtime!"); if (Settings.runningSetup) { log(-1, "Running Setup: ignoring this error for now"); mem = memx; return; } } Sikulix.terminate(110); } log(lvl, "Now loaded: %s from: \n%s", libname, lib); mem = memx; } private File extractLibs(String targetDir, String libSource) { String memx = mem; mem = "extractLibs"; if (apiJarURL != null) { libsURL = apiJarURL; targetDir = new File(libsURL.getPath()).getParent(); extractingFromJar = true; } List<String[]> libsList = makePackageFileList( (libsURL != null) ? libsURL : jarURL, libSource, false); if (libsList == null) { mem = memx; return null; } targetDir = FileManager.slashify(targetDir, true); String targetDirLibs = targetDir + "libs"; (new File(targetDirLibs)).mkdirs(); String targetName = null; File targetFile; long targetDate; for (String[] e : libsList) { try { targetName = e[0].substring(e[0].lastIndexOf("/") + 1); targetFile = new File(targetDirLibs, targetName); if (targetFile.exists()) { targetDate = targetFile.lastModified(); } else { targetDate = 0; } if (targetDate == 0 || targetDate < Long.valueOf(e[1])) { extractResource(e[0], targetFile, extractingFromJar); log(lvl + 1, "is from: %s (%d)", e[1], targetDate); } else { log(lvl + 1, "already in place: " + targetName); } } catch (IOException ex) { log(lvl, "IO-problem extracting: %s\n%s", targetName, ex.getMessage()); mem = memx; return null; } } mem = memx; return new File(targetDirLibs); } private List<String[]> makePackageFileList(URL jar, String path, boolean deep) { List<String[]> fList = new ArrayList<String[]>(); int iFile = 0; if (extractingFromJar) { try { ZipInputStream zip = new ZipInputStream(jar.openStream()); ZipEntry ze; log(lvl, "from:\n%s", FileManager.slashify(jar.getPath(), false)); while ((ze = zip.getNextEntry()) != null) { String entryName = ze.getName(); if (entryName.startsWith(path) && !entryName.endsWith("/")) { log(lvl + 2, "%d: %s", iFile, entryName); fList.add(new String[]{FileManager.slashify(entryName, false), String.format("%d", ze.getTime())}); iFile++; } } log(lvl, "Found %d Files in %s", iFile, path); } catch (IOException e) { log(-1, "Did not work!\n%s", e.getMessage()); return null; } } else { String p = FileManager.slashify(jar.getPath(), false); //TODO hack: to get folder Commands and Lib from Basics if (path.startsWith("Commands/") || path.startsWith("Lib/")) { p = p.replace("Natives", "Basics"); } File folder = new File(p, path); if (folder.isFile()) { fList.add(new String[]{FileManager.slashify(folder.getAbsolutePath(), false), String.format("%d", folder.lastModified())}); log(lvl, "Found 1 file in %s", path); } else { log(lvl, "from: " + folder.getAbsolutePath()); for (File f : getDeepFileList(folder, deep)) { log(lvl + 2, "file: " + f.getAbsolutePath()); fList.add(new String[]{FileManager.slashify(f.getAbsolutePath(), false), String.format("%d", f.lastModified())}); iFile++; } log(lvl, "Found %d file(s) in %s", iFile, path); } } return fList; } private List<File> getDeepFileList(File entry, boolean deep) { List<File> filelist = new ArrayList<File>(); if (entry.isDirectory()) { for (File f : entry.listFiles()) { if (f.isDirectory()) { if (!deep) { continue; } filelist.addAll(getDeepFileList(f, deep)); } else { filelist.add(f); } } } return filelist; } /** * extract a resource to a writable file * * @param resourcename the name of the resource on the classpath * @param outputfile the file to copy to * @return the extracted file * @throws IOException */ private File extractResource(String resourcename, File outputfile, boolean isJar) throws IOException { InputStream in; if (isJar) { in = cl.getResourceAsStream(resourcename); } else { in = new FileInputStream(resourcename); } if (in == null) { throw new IOException("Resource " + resourcename + " not on classpath"); } if (!outputfile.getParentFile().exists()) { outputfile.getParentFile().mkdirs(); } log0(lvl + 1, "Extracting resource from: " + resourcename); log0(lvl + 1, "Extracting to: " + outputfile.getAbsolutePath()); copyResource(in, outputfile); return outputfile; } private void copyResource(InputStream in, File outputfile) throws IOException { OutputStream out = null; try { out = new FileOutputStream(outputfile); copy(in, out); } catch (IOException e) { log0(-1, "copyResource Not possible: " + e.getMessage()); } finally { if (out != null) { out.close(); } } } /** * copy an InputStream to an OutputStream. * * @param in InputStream to copy from * @param out OutputStream to copy to * @throws IOException if there's an error */ private void copy(InputStream in, OutputStream out) throws IOException { byte[] tmp = new byte[8192]; int len; while (true) { len = in.read(tmp); if (len <= 0) { break; } out.write(tmp, 0, len); } } }