/* * Copyright (c) 2010-2016, Sikuli.org, sikulix.com * Released under the MIT License. * */ package org.sikuli.setup; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.LineBorder; import org.rauschig.jarchivelib.Archiver; import org.rauschig.jarchivelib.ArchiverFactory; import org.sikuli.basics.Debug; import org.sikuli.basics.FileManager; import org.sikuli.basics.SplashFrame; import org.sikuli.basics.PreferencesUser; import org.sikuli.script.RunTime; import org.sikuli.basics.Settings; //import org.sikuli.script.Sikulix; import org.sikuli.util.LinuxSupport; public class RunSetup { private static File fDownloadsGeneric = null; private static String downloadedFiles; private static boolean noSetup = false; private static String workDir; private static File fWorkDir; private static String logfile; private static String version; //TODO wrong if version number parts have more than one digit private static String minorversion; private static String majorversion; private static String updateVersion; private static String downloadIDE; private static String downloadAPI; private static String downloadLibsMac; private static String downloadLibsWin; private static String downloadLibsLux; private static String downloadRServer; private static String downloadJython; private static String downloadJython25; private static String downloadJRuby; private static String downloadJRubyAddOns; private static String localAPI = "sikulixapi.jar"; private static String localIDE = "sikulix.jar"; private static String localSetup; private static String localTess = "sikulixtessdata.jar"; private static String localJython = "sikulixjython.jar"; private static String localJRuby = "sikulixjruby.jar"; private static String localJRubyAddOns = "sikulixjrubyaddons.jar"; private static String runsikulix = "runsikulix"; private static String localLogfile; private static SetUpSelect winSU; private static JFrame winSetup; private static boolean getIDE, getJython, getAPI; private static boolean getRServer = false; private static boolean forAllSystems = false; private static boolean getTess = false; private static boolean getJRuby = false; private static boolean getJRubyAddOns = false; private static String localJar; private static boolean hasOptions = false; private static List<String> options = new ArrayList<String>(); private static JFrame splash = null; private static String me = "RunSetup"; private static int lvl = 2; private static String msg; private static boolean shouldPackBundledLibs = true; private static long start; private static boolean logToFile = true; private static boolean forSystemWin = false; private static boolean forSystemMac = false; private static boolean forSystemLux = false; private static String libsMac = "sikulixlibsmac"; private static String libsWin = "sikulixlibswin"; private static String libsLux = "sikulixlibslux"; private static File folderLib; private static File folderLibsWin; private static File folderLibsLux; private static String linuxDistro = "*** testing Linux ***"; private static String osarch; //TODO set true to test on Mac private static boolean isLinux = false; private static boolean libsProvided = false; private static String[] addonFileList = new String[]{null, null, null, null, null}; private static String[] addonFilePrefix = new String[]{null, null, null, null, null}; private static int addonVision = 0; private static int addonGrabKey = 1; private static int addonLibswindows = 2; private static int addonFolderLib = 3; private static boolean notests = false; private static boolean clean = false; private static RunTime runTime; private static File fDownloadsGenericApp; private static boolean useLibsProvided = false; private static File fDownloadsObsolete; private static boolean runningWithProject = false; private static boolean shouldBuildVision = false; private static boolean bequiet = false; private static String sikulixMavenGroup = "com/sikulix/"; private static boolean withExtensions = false; static Map<String, String> downloadsLookfor = new HashMap<String, String>(); static Map<String, File> downloadsFound = new HashMap<String, File>(); private static File fSetupStuff = null; private static boolean hasAPI = true; private static String[] jarsList = new String[]{ null, // ide null, // api null, // tess null, // jython null, // jruby null, // jruby+ null, // libwin null, // libmac null // liblux }; private static boolean testingMaven = false; private static boolean useLocalMavenRepo = false; //<editor-fold defaultstate="collapsed" desc="new logging concept"> private static void logp(String message, Object... args) { System.out.println(String.format(message, args)); } private static void log(int level, String message, Object... args) { Debug.logx(level, me + ": " + message, args); } private static void logPlus(int level, String message, Object... args) { String sout = Debug.logx(level, me + ": " + message, args); if (logToFile) { System.out.println(sout); } } //</editor-fold> public static void main(String[] args) throws IOException { runTime = RunTime.get(RunTime.Type.SETUP, args); version = runTime.getVersionShort(); minorversion = runTime.getVersionShort().substring(0, 5); majorversion = runTime.getVersionShort().substring(0, 3); if (args.length > 0 && "test".equals(args[0])) testingMaven = true; localSetup = String.format("sikulixsetup-%s-%s-project.jar", version, runTime.sxBuildStamp); if (runTime.fSxBaseJar.getPath().contains(localSetup)) { runningWithProject = true; } if (!testingMaven && (runTime.runningInProject || runningWithProject)) { runningWithProject = true; runTime.shouldCleanDownloads = true; downloadIDE = String.format("sikulixsetupIDE-%s-%s.jar", version, runTime.sxBuildStamp); downloadAPI = String.format("sikulixsetupAPI-%s-%s.jar", version, runTime.sxBuildStamp); downloadLibsMac = String.format("sikulixlibsmac-%s-%s.jar", version, runTime.sxBuildStamp); downloadLibsWin = String.format("sikulixlibswin-%s-%s.jar", version, runTime.sxBuildStamp); downloadLibsLux = String.format("sikulixlibslux-%s-%s.jar", version, runTime.sxBuildStamp); } else { localSetup = "sikulixsetup-" + version + ".jar"; downloadIDE = getMavenJarName("sikulixsetupIDE#forsetup"); downloadAPI = getMavenJarName("sikulixsetupAPI#forsetup"); downloadLibsMac = getMavenJarName("sikulixlibsmac"); downloadLibsWin = getMavenJarName("sikulixlibswin"); downloadLibsLux = getMavenJarName("sikulixlibslux"); } downloadJython = new File(runTime.SikuliJythonMaven).getName(); downloadJython25 = new File(runTime.SikuliJythonMaven25).getName(); downloadJRuby = new File(runTime.SikuliJRubyMaven).getName(); // CodeSource codeSrc = RunSetup.class.getProtectionDomain().getCodeSource(); // if (codeSrc != null && codeSrc.getLocation() != null) { // codeSrc.getLocation(); // } else { // log(-1, "Fatal Error 201: Not possible to accessjar file for RunSetup.class"); // Sikulix.terminate(201); // } if (runTime.SikuliVersionBetaN > 0 && runTime.SikuliVersionBetaN < 99) { updateVersion = String.format("%d.%d.%d-Beta%d", runTime.SikuliVersionMajor, runTime.SikuliVersionMinor, runTime.SikuliVersionSub, 1 + runTime.SikuliVersionBetaN); } else if (runTime.SikuliVersionBetaN < 1) { updateVersion = String.format("%d.%d.%d", runTime.SikuliVersionMajor, runTime.SikuliVersionMinor, 1 + runTime.SikuliVersionSub); } else { updateVersion = String.format("%d.%d.%d", runTime.SikuliVersionMajor, 1 + runTime.SikuliVersionMinor, 0); } options.addAll(Arrays.asList(args)); //<editor-fold defaultstate="collapsed" desc="options return version"> if (args.length > 0 && "stamp".equals(args[0])) { System.out.println(runTime.SikuliProjectVersion + "-" + runTime.sxBuildStamp); System.exit(0); } if (args.length > 0 && "frommavenforsed".equals(args[0])) { bequiet = true; String name = getMavenJarPath(args[2]); if (name == null) { name = runTime.dlMavenSnapshot + sikulixMavenGroup; } name = name.replaceAll("/", "\\\\/"); System.out.println(name); System.exit(0); } if (args.length > 0 && "build".equals(args[0])) { System.out.println(runTime.SikuliVersionBuild); System.exit(0); } if (args.length > 0 && "pversion".equals(args[0])) { System.out.println(runTime.SikuliProjectVersion); System.exit(0); } if (args.length > 0 && "uversion".equals(args[0])) { System.out.println(runTime.SikuliProjectVersionUsed); System.exit(0); } if (args.length > 0 && "version".equals(args[0])) { System.out.println(runTime.getVersionShort()); System.exit(0); } if (args.length > 0 && "minorversion".equals(args[0])) { System.out.println(minorversion); System.exit(0); } if (args.length > 0 && "majorversion".equals(args[0])) { System.out.println(majorversion); System.exit(0); } if (args.length > 0 && "updateversion".equals(args[0])) { System.out.println(updateVersion); System.exit(0); } //</editor-fold> if (options.size() > 0 && "noSetup".equals(options.get(0))) { noSetup = true; options.remove(0); } if (options.size() > 0 && "test".equals(options.get(0))) { testingMaven = true; if (runTime.isVersionRelease()) { useLocalMavenRepo = true; } options.remove(0); } //TODO add parameter for proxy settings, linux options if (options.size() > 0 && "options".equals(options.get(0))) { options.remove(0); if (!options.isEmpty()) { for (String val : options) { if (val.contains("1.1")) { hasOptions = true; getIDE = true; getJython = true; } else if (val.contains("1.2")) { hasOptions = true; getIDE = true; getJRuby = true; } else if (val.contains("1.3")) { hasOptions = true; getIDE = true; getJRuby = true; getJRubyAddOns = true; } else if ("2".equals(val)) { hasOptions = true; getAPI = true; } else if ("3".equals(val)) { hasOptions = true; getTess = true; } else if ("4".equals(val)) { hasOptions = true; forAllSystems = true; } else if (val.contains("4.1")) { hasOptions = true; forSystemWin = true; } else if (val.contains("4.2")) { hasOptions = true; forSystemMac = true; } else if (val.contains("4.3")) { hasOptions = true; forSystemLux = true; } else if ("5".equals(val)) { hasOptions = true; getRServer = true; } else if (val.toLowerCase().startsWith("lib")) { hasOptions = true; libsProvided = true; } else if (val.toLowerCase().startsWith("buildv")) { hasOptions = true; shouldBuildVision = true; } else if (val.toLowerCase().startsWith("not")) { notests = true; } else if (val.toLowerCase().startsWith("clean")) { clean = true; } else if (val.toLowerCase().startsWith("ext")) { hasOptions = true; withExtensions = true; } } options.clear(); } } if (!hasOptions && !testingMaven) { String msg = String.format("You are about to run a setup for %s (%s)", version, runTime.sxBuildStamp); msg += "\n\nYou should have a suitable backup, "; msg += "\nto go back in case to what you have now."; msg += "\n\nClick NO to stop here"; if (!popAsk(msg)) { userTerminated(""); } } localLogfile = "SikuliX-" + version + "-SetupLog.txt"; if (options.size() > 0) { if (!"-jar".equals(options.get(0))) { System.out.println("invalid command line options - terminating"); for (String opt : options) { System.out.println("option: " + opt); } System.exit(-1); } log(lvl, "Seems to be run using mvn exec:exec"); } else { log(lvl, "command line options:"); String strArgs = ""; for (String arg : args) { strArgs += arg + " "; } log(lvl, "%s", strArgs); } //<editor-fold defaultstate="collapsed" desc="general preps"> Settings.runningSetup = true; Settings.LogTime = true; runTime.makeFolders(); fWorkDir = runTime.fSxBase; fDownloadsGeneric = runTime.fSikulixDownloadsGeneric; fDownloadsGeneric.mkdirs(); fDownloadsGenericApp = runTime.fSikulixDownloadsBuild; fDownloadsGenericApp.mkdirs(); if (testingMaven || runTime.runningInProject) { fWorkDir = runTime.fSikulixSetup; fWorkDir.mkdir(); } fDownloadsObsolete = new File(fWorkDir, "Downloads"); workDir = fWorkDir.getAbsolutePath(); fSetupStuff = new File(fWorkDir, "SetupStuff"); FileManager.resetFolder(fSetupStuff); osarch = "" + runTime.javaArch; if (runTime.runningLinux) { linuxDistro = runTime.linuxDistro; isLinux = true; } if (!testingMaven && runTime.runningInProject) { if (noSetup) { log(lvl, "creating Setup folder - not running setup"); } else { log(lvl, "have to create Setup folder before running setup"); } if (!createSetupFolder(fWorkDir)) { log(-1, "createSetupFolder: did not work- terminating"); System.exit(1); } if (noSetup) { System.exit(0); } logToFile = false; } checkDownloads(); // if (!testingMaven) { // logToFile = true; // } if (logToFile) { logfile = (new File(fWorkDir, localLogfile)).getAbsolutePath(); if (!Debug.setLogFile(logfile)) { popError(workDir + "\n... folder we are running in must be user writeable! \n" + "please correct the problem and start again."); System.exit(0); } } if (args.length > 0) { logPlus(lvl, "... starting with: " + arrayToString(args)); } else { logPlus(lvl, "... starting with no args given"); } if (isLinux) { logPlus(lvl, "LinuxDistro: %s (%s-Bit)", linuxDistro, osarch); } logPlus(lvl, "Setup: %s %s in folder:\n%s", runTime.getVersionShort(), runTime.SikuliVersionBuild, fWorkDir); File localJarIDE = new File(fWorkDir, localIDE); File localJarAPI = new File(fWorkDir, localAPI); folderLibsWin = new File(fSetupStuff, "sikulixlibs/windows"); folderLib = new File(fSetupStuff, "Lib"); folderLibsLux = runTime.fLibsProvided; //TODO Windows 8 HKLM/SOFTWARE/JavaSoft add Prefs ???? boolean success; if (!libsProvided && LinuxSupport.existsLibs()) { if (popAsk(String.format("Found a libs folder at\n%s\n" + "Click YES to use the contained libs " + "for setup (be sure they are useable).\n" + "Click NO to make a clean setup (libs are deleted).", folderLibsLux))) { useLibsProvided = true; } else { FileManager.resetFolder(folderLibsLux); } } //</editor-fold> //<editor-fold defaultstate="collapsed" desc="display setup options"> String proxyMsg = ""; if (!hasOptions) { getIDE = false; getJython = false; getAPI = false; winSetup = new JFrame("SikuliX-Setup"); Border rpb = new LineBorder(Color.YELLOW, 8); winSetup.getRootPane().setBorder(rpb); Container winCP = winSetup.getContentPane(); winCP.setLayout(new BorderLayout()); winSU = new SetUpSelect(); winCP.add(winSU, BorderLayout.CENTER); winSU.option2.setSelected(true); winSetup.pack(); winSetup.setLocationRelativeTo(null); winSetup.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); winSetup.setVisible(true); //setup version basic winSU.suVersion.setText(runTime.getVersionShort() + " (" + runTime.SikuliVersionBuild + ")"); // running system Settings.getOS(); msg = runTime.osName + " " + Settings.getOSVersion(); if (isLinux) { msg += " (" + linuxDistro + ")"; } winSU.suSystem.setText(msg); logPlus(lvl, "RunningSystem: " + msg); // folder running in winSU.suFolder.setText(workDir); logPlus(lvl, "parent of jar/classes: %s", workDir); // running Java String osarch = System.getProperty("os.arch"); msg = "Java " + Settings.JavaVersion + " (" + Settings.JavaArch + ") " + Settings.JREVersion; winSU.suJava.setText(msg); logPlus(lvl, "RunningJava: " + msg); PreferencesUser prefs = PreferencesUser.getInstance(); boolean prefsHaveProxy = false; String pName = prefs.get("ProxyName", ""); String pPort = prefs.get("ProxyPort", ""); if (!pName.isEmpty() && !pPort.isEmpty()) { prefsHaveProxy = true; winSU.pName.setText(pName); winSU.pPort.setText(pPort); } winSU.addPropertyChangeListener("background", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent pce) { winSetup.setVisible(false); } }); while (true) { if (winSU.getBackground() == Color.YELLOW) { break; } try { Thread.sleep(1000); } catch (InterruptedException ex) { } } pName = winSU.pName.getText(); pPort = winSU.pPort.getText(); if (!pName.isEmpty() && !pPort.isEmpty()) { if (FileManager.setProxy(pName, pPort)) { logPlus(lvl, "Requested to run with proxy: %s ", Settings.proxy); proxyMsg = "... using proxy: " + Settings.proxy; } } else if (prefsHaveProxy) { prefs.put("ProxyName", ""); prefs.put("ProxyPort", ""); } Settings.proxyChecked = true; //</editor-fold> //<editor-fold defaultstate="collapsed" desc="evaluate setup options"> if (winSU.option1.isSelected()) { getIDE = true; if (winSU.option2.isSelected()) { getJython = true; } if (winSU.option3.isSelected()) { getJRuby = true; } if (!getJython && !getJRuby) { getIDE = false; } } if (winSU.option4.isSelected()) { getAPI = true; } if (winSU.option5.isSelected()) { getTess = true; } // if (winSU.option6.isSelected()) { // forAllSystems = true; // } // if (winSU.option7.isSelected()) { // getRServer = true; // } if (((getTess || forAllSystems) && !(getIDE || getAPI))) { popError("You only selected Option 3 !\n" + "This is currently not supported.\n" + "Please start allover again with valid options.\n"); terminate(""); } msg = "The following file(s) will be downloaded to\n" + workDir + "\n"; } downloadedFiles = ""; if (getIDE || getAPI || getRServer) { if (!proxyMsg.isEmpty()) { msg += proxyMsg + "\n"; } if (forAllSystems) { msg += "\n--- Native support libraries for all systems (sikulixlibs...)\n"; downloadedFiles += downloadLibsWin + " "; downloadedFiles += downloadLibsMac + " "; downloadedFiles += downloadLibsLux + " "; } else { msg += "\n--- Native support libraries for " + runTime.osName + " (sikulixlibs...)\n"; if (runTime.runningWindows) { downloadedFiles += downloadLibsWin + " "; } else if (runTime.runningMac) { downloadedFiles += downloadLibsMac + " "; } else if (runTime.runningLinux) { downloadedFiles += downloadLibsLux + " "; } } if (getIDE) { downloadedFiles += downloadIDE + " "; downloadedFiles += downloadAPI + " "; msg += "\n--- Package 1 ---\n" + downloadIDE + " (IDE/Scripting)\n" + downloadAPI + " (Java API)"; if (getJython) { downloadedFiles += downloadJython + " "; msg += "\n - with Jython"; } if (getJRuby) { downloadedFiles += downloadJRuby + " "; msg += "\n - with JRuby"; if (downloadJRubyAddOns != null) { if (getJRubyAddOns) { downloadedFiles += downloadJRubyAddOns + " "; msg += " incl. AddOns"; } } else { getJRubyAddOns = false; } } if (Settings.isMac()) { msg += "\n - creating Mac application"; } msg += "\n"; } if (getAPI) { msg += "\n--- Package 2 ---\n" + downloadAPI; if (!getIDE) { downloadedFiles += downloadAPI + " "; msg += " (Java API)"; } else { msg += " (done in package 1)"; } } if (getTess || getRServer) { if (getIDE || getAPI) { msg += "\n"; } msg += "\n--- Additions ---"; if (getTess) { downloadedFiles += "tessdata-eng" + " "; msg += "\n" + "tessdata-eng" + " (Tesseract)"; } if (downloadRServer != null) { if (getRServer) { downloadedFiles += downloadRServer + " "; msg += "\n" + downloadRServer + " (RemoteServer)"; } } else { getRServer = false; } } } if (getIDE || getAPI || getRServer || withExtensions) { msg += "\n\nOnly click NO, if you want to terminate setup now!\n" + "Click YES even if you want to use local copies in Downloads!"; if (!popAsk(msg)) { terminate(""); } } else { popError("Nothing selected! You might try again ;-)"); terminate(""); } //</editor-fold> String localTemp = "sikulixtemp.jar"; localJar = null; File fTargetJar; String targetJar; boolean downloadOK = true; boolean dlOK = true; downloadOK = true; // String dlDirBuild = fDownloadsBuild.getAbsolutePath(); String dlDirGenericApp = fDownloadsGenericApp.getAbsolutePath(); String dlDirGeneric = fDownloadsGeneric.getAbsolutePath(); String dlDownloads = fDownloadsObsolete.getAbsolutePath(); boolean shouldUseDownloads = hasOptions && fDownloadsObsolete.exists(); String dlDir = shouldUseDownloads ? dlDownloads : dlDirGenericApp; if (!forSystemWin && !forSystemMac && !forSystemLux) { forSystemLux = isLinux; if (!isLinux) { forSystemWin = Settings.isWindows(); forSystemMac = Settings.isMac(); } } File fDownloaded = null; String sDownloaded; String sDownloadedName; //<editor-fold defaultstate="collapsed" desc="download lib jars"> if (testingMaven) { fDownloaded = downloadJarFromMavenSx("sikulixsetup#forsetup", fWorkDir.getAbsolutePath(), "sikulixsetup"); if (fDownloaded == null) { logPlus(-1, "%s not possible to copy from local MavenRepo"); downloadOK = false; } String fpDownloaded = fDownloaded.getAbsolutePath(); fpDownloaded = fpDownloaded.replace("-forsetup", ""); fDownloaded.renameTo(new File(fpDownloaded)); } if (getIDE || getAPI) { if (forSystemLux || forAllSystems) { jarsList[8] = new File(workDir, libsLux + ".jar").getAbsolutePath(); fDownloaded = downloadedAlready("lux", "Linux native libs", true); if (fDownloaded == null) { fDownloaded = downloadJarFromMavenSx(libsLux, dlDir, libsLux); } downloadOK &= copyFromDownloads(fDownloaded, libsLux, jarsList[8]); if (downloadOK && isLinux) { runTime.addToClasspath(jarsList[8]); runTime.dumpClassPath("sikulix"); if (shouldBuildVision) { logPlus(lvl, "Requested to build libVisionProxy.so on the fly"); if (!LinuxSupport.haveToBuild()) { terminate("Building libVisionproxy.so not possible - check the log"); } } logPlus(lvl, "checking usability of bundled, provided or built libs"); if (!RunTime.loadLibrary(LinuxSupport.slibVision, useLibsProvided)) { logPlus(-1, "libVisionproxy.so finally not useable"); terminate("Giving up!"); } else logPlus(lvl, "Bundled, provided or built libVisionproxy.so is useable"); useLibsProvided = runTime.useLibsProvided || LinuxSupport.shouldUseProvided; } } if (forSystemWin || forAllSystems) { jarsList[6] = new File(workDir, libsWin + ".jar").getAbsolutePath(); fDownloaded = downloadedAlready("win", "Windows native libs", true); if (fDownloaded == null) { fDownloaded = downloadJarFromMavenSx(libsWin, dlDir, libsWin); } boolean dlLibsWinOK = copyFromDownloads(fDownloaded, libsWin, jarsList[6]); if (dlLibsWinOK) { FileManager.resetFolder(folderLibsWin); String aJar = FileManager.normalizeAbsolute(jarsList[6], false); if (null == runTime.resourceListAsSikulixContentFromJar(aJar, "sikulixlibs/windows", folderLibsWin, null)) { terminate("libswin content list could not be created", 999); } addonFileList[addonLibswindows] = new File(folderLibsWin, runTime.fpContent).getAbsolutePath(); addonFilePrefix[addonLibswindows] = libsWin; } downloadOK &= dlLibsWinOK; } if (forSystemMac || forAllSystems) { jarsList[7] = new File(workDir, libsMac + ".jar").getAbsolutePath(); fDownloaded = downloadedAlready("mac", "Mac native libs", true); if (fDownloaded == null) { fDownloaded = downloadJarFromMavenSx(libsMac, dlDir, libsMac); } downloadOK &= copyFromDownloads(fDownloaded, libsMac, jarsList[7]); } } //</editor-fold> //<editor-fold defaultstate="collapsed" desc="download IDE/API Jython/JRuby ..."> if (getIDE || getAPI) { sDownloaded = "sikulixapi"; localJar = new File(workDir, localAPI).getAbsolutePath(); fDownloaded = downloadedAlready("api", "Java API package", true); if (fDownloaded == null) { fDownloaded = downloadJarFromMavenSx("sikulixsetupAPI#forsetup", dlDir, sDownloaded); } boolean dlApiOK = copyFromDownloads(fDownloaded, sDownloaded, localJar); if (dlApiOK && (forSystemWin || forAllSystems)) { FileManager.resetFolder(folderLib); String aJar = FileManager.normalizeAbsolute(localJar, false); if (null == runTime.resourceListAsSikulixContentFromJar(aJar, "Lib", folderLib, null)) { terminate("Lib content list could not be created", 999); } addonFileList[addonFolderLib] = new File(folderLib, runTime.fpContent).getAbsolutePath(); addonFilePrefix[addonFolderLib] = "Lib"; } downloadOK &= dlApiOK; } if (getIDE) { sDownloaded = "sikulix"; localJar = new File(workDir, localIDE).getAbsolutePath(); fDownloaded = downloadedAlready("ide", "SikuliX IDE package", true); if (fDownloaded == null) { fDownloaded = downloadJarFromMavenSx("sikulixsetupIDE#forsetup", dlDir, sDownloaded); } downloadOK &= copyFromDownloads(fDownloaded, sDownloaded, localJar); } if (getJython) { sDownloaded = "Jython"; targetJar = new File(workDir, localJython).getAbsolutePath(); if (Settings.isJava6()) { logPlus(lvl, "running on Java 6: need to use Jython 2.5 - which is downloaded"); fDownloaded = downloadedAlready("python25", "Jython 2.5", false); if (fDownloaded == null) { fDownloaded = downloadJarFromMaven(runTime.SikuliJythonMaven25, dlDirGeneric, sDownloaded); } downloadedFiles.replace(downloadJython, downloadJython25); } else { if (popAsk("If you click YES, you will get Jython version 2.7.0 (recommended)\n" + "... but in rare cases there might be issues with UTF-8/Unicode\n" + "that usually appear on startup when UTF-8 characters\n" + "are present somewhere in the system environment\n" + "If you encounter such problems with Jython 2.7.0\n" + "run setup again and\n" + "click NO to get Jython 2.5.4rc1")) { // TODO: use runtime.SikuliJythonVersion25 in the message above sDownloadedName = new File(runTime.SikuliJythonMaven).getName(); fDownloaded = downloadedAlready("python", "Jython 2.7", false); if (fDownloaded == null) { fDownloaded = downloadJarFromMaven(runTime.SikuliJythonMaven, dlDirGeneric, sDownloaded); } } else { fDownloaded = downloadedAlready("python25", "Jython 2.5", false); if (fDownloaded == null) { fDownloaded = downloadJarFromMaven(runTime.SikuliJythonMaven25, dlDirGeneric, sDownloaded); } downloadedFiles = downloadedFiles.replace(downloadJython, downloadJython25); } } downloadOK &= copyFromDownloads(fDownloaded, sDownloaded, targetJar); } if (getJRuby) { sDownloaded = "JRuby"; sDownloadedName = new File(runTime.SikuliJRubyMaven).getName(); targetJar = new File(workDir, localJRuby).getAbsolutePath(); fDownloaded = downloadsFound.get("ruby"); if (fDownloaded == null) { fDownloaded = downloadJarFromMaven(runTime.SikuliJRubyMaven, dlDirGeneric, sDownloaded); } downloadOK &= copyFromDownloads(fDownloaded, sDownloaded, targetJar); if (downloadOK && getJRubyAddOns) { sDownloaded = "JRuby AddOns"; targetJar = new File(workDir, localJRubyAddOns).getAbsolutePath(); fDownloaded = downloadsFound.get("rubyaddons"); fDownloaded = download(runTime.downloadBaseDir, dlDirGeneric, downloadJRubyAddOns, sDownloaded); downloadOK &= copyFromDownloads(fDownloaded, sDownloaded, targetJar); } } if (downloadOK && withExtensions) { for (String item : runTime.standardExtensions) { sDownloaded = item; sDownloadedName = item + ".jar"; fTargetJar = new File(runTime.fSikulixExtensions, sDownloadedName); if (!fTargetJar.exists()) { fDownloaded = download(runTime.downloadBaseDir, runTime.fSikulixExtensions.getAbsolutePath(), sDownloadedName, item); downloadOK &= fDownloaded != null; } else { logPlus(lvl, "request to download: %s ignored - already there", sDownloadedName); } } } //</editor-fold> //<editor-fold defaultstate="collapsed" desc="download for tesseract"> if (getTess) { String langTess = "eng"; targetJar = new File(workDir, localTess).getAbsolutePath(); String xTess = runTime.tessData.get(langTess); String[] xTessNames = xTess.split("/"); String xTessName = xTessNames[xTessNames.length - 1]; String tessFolder = "tessdata-" + langTess; File fArchiv = downloadedAlready("tess", "Tesseract tessdata-eng", false); if (fArchiv == null) { fArchiv = download(xTess, dlDirGeneric, null, tessFolder); logPlus(lvl, "downloaded: %s", tessFolder); } else { logPlus(lvl, "using already downloaded: %s", tessFolder); } File fTessWork = fArchiv.getParentFile(); log(lvl, "trying to extract from: %s", xTessName); Archiver archiver = ArchiverFactory.createArchiver("tar", "gz"); archiver.extract(fArchiv, fTessWork); File fTess = new File(fTessWork, "tesseract-ocr/tessdata"); if (!fTess.exists()) { logPlus(-1, "Download: tessdata: version: eng - did not work"); downloadOK = false; } else { File fTessData = new File(fTessWork, tessFolder); log(lvl, "preparing the tessdata stuff in:\n%s", fTessData.getAbsolutePath()); FileManager.resetFolder(fTessData); FileManager.xcopy(fTess.getAbsolutePath(), fTessData.getAbsolutePath()); FileManager.deleteFileOrFolder(fTess.getParent()); runTime.extractResourcesToFolder("sikulixtessdata", fTessData, null); log(lvl, "finally preparing %s", localTess); fTargetJar = (new File(workDir, localTemp)); targetJar = fTargetJar.getAbsolutePath(); String tessJar = new File(workDir, localTess).getAbsolutePath(); success = runTime.addToClasspath(fTessData.getParent()); runTime.resourceListAsSikulixContent(tessFolder, fTessData, null); downloadOK &= FileManager.buildJar("#" + targetJar, new String[]{}, new String[]{fTessData.getAbsolutePath()}, new String[]{"sikulixtessdata"}, null); downloadOK &= handleTempAfter(targetJar, tessJar); FileManager.deleteFileOrFolder(fTessData.getAbsolutePath()); } } //</editor-fold> if (!downloadedFiles.isEmpty()) { logPlus(lvl, "Download ended"); logPlus(lvl, "Downloads for selected options:\n" + downloadedFiles); } if (!downloadOK) { msg = "Some of the downloads did not complete successfully.\n" + "Check the logfile for possible error causes.\n\n" + "If you think, setup's inline download is blocked somehow on\n" + "your system, you might download the appropriate raw packages manually\n" + "into the folder Downloads in the setup folder and run setup again.\n\n" + "files to download (information is in the setup log file too)\n\n"; for (String fnToDownload : downloadedFiles.split(" ")) { msg += fnToDownload + "\n"; } msg += "\nBe aware: The raw packages are not useable without being processed by setup!\n\n" + "For other reasons, you might simply try to run setup again."; popError(msg); terminate("download not completed successfully", 1); } //<editor-fold defaultstate="collapsed" desc="create jars and add needed stuff"> if (!getIDE && !getAPI) { logPlus(lvl, "Nothing else to do"); System.exit(0); } if (isLinux) { if (libsProvided || useLibsProvided) { shouldPackBundledLibs = false; } if (!shouldPackBundledLibs) { addonFileList[addonVision] = new File(folderLibsLux, LinuxSupport.libVision).getAbsolutePath(); addonFileList[addonGrabKey] = new File(folderLibsLux, LinuxSupport.libGrabKey).getAbsolutePath(); for (int i = 0; i < 2; i++) { if (!new File(addonFileList[i]).exists()) { addonFileList[i] = null; } else { logPlus(lvl, "user provided lib: %s", addonFileList[i]); } } String libPrefix = "sikulixlibs/linux/libs" + osarch; logPlus(lvl, "libs will be stored in jar at %s", libPrefix); addonFilePrefix[addonVision] = libPrefix; addonFilePrefix[addonGrabKey] = libPrefix; } } success = true; FileManager.JarFileFilter libsFilter = new FileManager.JarFileFilter() { @Override public boolean accept(ZipEntry entry, String jarname) { if (!forAllSystems) { if (forSystemWin) { if (entry.getName().startsWith("sikulixlibs/mac") || entry.getName().startsWith("sikulixlibs/linux") || entry.getName().endsWith("sikulixfoldercontent") || entry.getName().startsWith("jxgrabkey")) { return false; } } else if (forSystemMac) { if (entry.getName().startsWith("sikulixlibs/windows") || entry.getName().startsWith("sikulixlibs/linux") || entry.getName().startsWith("com.melloware.jintellitype") || entry.getName().startsWith("jxgrabkey")) { return false; } } else if (forSystemLux) { if (entry.getName().startsWith("sikulixlibs/windows") || entry.getName().startsWith("sikulixlibs/mac") || entry.getName().startsWith("com.melloware.jintellitype")) { return false; } } } if (forSystemLux || forAllSystems) { if (!shouldPackBundledLibs && entry.getName().contains(LinuxSupport.libVision) && entry.getName().contains("libs" + osarch)) { if (new File(folderLibsLux, LinuxSupport.libVision).exists()) { logPlus(lvl, "Adding provided lib: %s (libs%s)", LinuxSupport.libVision, osarch); return false; } else { return true; } } if (!shouldPackBundledLibs && entry.getName().contains(LinuxSupport.libGrabKey) && entry.getName().contains("libs" + osarch)) { if (new File(folderLibsLux, LinuxSupport.libGrabKey).exists()) { logPlus(lvl, "Adding provided lib: %s (libs%s)", LinuxSupport.libGrabKey, osarch); return false; } else { return true; } } } return true; } }; splash = showSplash("Now creating jars, application and commandfiles", "please wait - may take some seconds ..."); File fAPI = new File(workDir, localAPI); jarsList[1] = fAPI.getAbsolutePath(); hasAPI = fAPI.exists(); if (getTess) { jarsList[2] = (new File(workDir, localTess)).getAbsolutePath(); } if (success && getAPI) { logPlus(lvl, "adding needed stuff to sikulixapi.jar"); localJar = (new File(workDir, localAPI)).getAbsolutePath(); targetJar = (new File(workDir, localTemp)).getAbsolutePath(); success &= FileManager.buildJar("#" + targetJar, jarsList, addonFileList, addonFilePrefix, libsFilter); success &= handleTempAfter(targetJar, localJar); } if (getAPI && getTess) { new File(workDir, localTess).delete(); jarsList[2] = null; } if (success && getIDE) { logPlus(lvl, "adding needed stuff to sikulix.jar"); localJar = (new File(workDir, localIDE)).getAbsolutePath(); jarsList[0] = localJar; if (getJython) { jarsList[3] = (new File(workDir, localJython)).getAbsolutePath(); } if (getJRuby) { jarsList[4] = (new File(workDir, localJRuby)).getAbsolutePath(); if (getJRubyAddOns) { jarsList[5] = (new File(workDir, localJRubyAddOns)).getAbsolutePath(); } } targetJar = (new File(workDir, localTemp)).getAbsolutePath(); success &= FileManager.buildJar("#" + targetJar, jarsList, null, null, libsFilter); success &= handleTempAfter(targetJar, localJar); if (Settings.isMac()) { logPlus(lvl, "making the Mac application Sikulix.app"); String macAppContentOrg = "macapp"; File fMacApp = new File(workDir, "SikuliX.app"); if (null == runTime.extractResourcesToFolder(macAppContentOrg, fMacApp, null)) { log(-1, "did not work"); } else { File fMacAppjar = new File(fMacApp, "Contents/Java/" + localIDE); new File(fMacApp, "run").setExecutable(true); new File(fMacApp, "Contents/MacOS/JavaAppLauncher").setExecutable(true); fMacAppjar.getParentFile().mkdirs(); FileManager.xcopy(new File(localJar), fMacAppjar); FileManager.deleteFileOrFolder(new File(localJar)); localJarIDE = fMacAppjar; } } } if (success && getIDE) { logPlus(lvl, "processing commandfiles"); if (runTime.runningWindows) { runTime.extractResourceToFile("Commands/windows", runsikulix + ".cmd", fWorkDir); } else if (runTime.runningMac) { runTime.extractResourceToFile("Commands/mac", runsikulix, fWorkDir); new File(fWorkDir, runsikulix).setExecutable(true); } else if (isLinux) { runTime.extractResourceToFile("Commands/linux", runsikulix, fWorkDir); new File(fWorkDir, runsikulix).setExecutable(true); new File(fWorkDir, localIDE).setExecutable(true); } } closeSplash(splash); if (!success) { popError("Bad things happened trying to add native stuff to selected jars --- terminating!"); terminate("Adding stuff to jars did not work"); } //</editor-fold> if (!notests && runTime.isHeadless()) { log(lvl, "Running headless --- skipping tests"); } //<editor-fold defaultstate="collapsed" desc="api test"> boolean runAPITest = false; if (getAPI && !notests && !runTime.isHeadless()) { logPlus(lvl, "Trying to run functional test: JAVA-API"); splash = showSplash("Trying to run functional test(s) - wait for the result popup", "Java-API: org.sikuli.script.Sikulix.testSetup()"); start += 2000; if (!runTime.addToClasspath(localJarAPI.getAbsolutePath())) { closeSplash(splash); log(-1, "Java-API test: "); popError("Something serious happened! Sikuli not useable!\n" + "Check the error log at " + (logfile == null ? "printout" : logfile)); terminate("Functional test JAVA-API did not work", 1); } try { log(lvl, "trying to run org.sikuli.script.Sikulix.testSetup()"); Class sysclass = URLClassLoader.class; Class SikuliCL = sysclass.forName("org.sikuli.script.Sikulix"); log(lvl, "class found: " + SikuliCL.toString()); Method method = null; if (hasOptions) { method = SikuliCL.getDeclaredMethod("testSetupSilent", new Class[0]); } else { method = SikuliCL.getDeclaredMethod("testSetup", new Class[0]); } log(lvl, "getMethod: " + method.toString()); method.setAccessible(true); closeSplash(splash); log(lvl, "invoke: " + method.toString()); Object ret = method.invoke(null, new Object[0]); if (!(Boolean) ret) { throw new Exception("testSetup returned false"); } } catch (Exception ex) { closeSplash(splash); log(-1, ex.getMessage()); popError("Something serious happened! Sikuli not useable!\n" + "Check the error log at " + (logfile == null ? "printout" : logfile)); terminate("Functional test Java-API did not work", 1); } runAPITest = true; } //</editor-fold> //<editor-fold defaultstate="collapsed" desc="ide test"> if (getIDE && !notests && !runTime.isHeadless()) { success = true; if (!runTime.addToClasspath(localJarIDE.getAbsolutePath())) { closeSplash(splash); popError("Something serious happened! Sikuli not useable!\n" + "Check the error log at " + (logfile == null ? "printout" : logfile)); terminate("Functional test IDE did not work", 1); } if (!runAPITest) { runTime.makeFolders(); } String testMethod; if (getJython) { if (hasOptions) { testMethod = "print \"testSetup: Jython: success\""; } else { testMethod = "Sikulix.testSetup(\"Jython Scripting\")"; } logPlus(lvl, "Jython: Trying to run functional test: running script statements via SikuliScript"); splash = showSplash("Jython Scripting: Trying to run functional test - wait for the result popup", "Running script statements via SikuliScript"); start += 2000; try { String testargs[] = new String[]{"-testSetup", "jython", testMethod}; closeSplash(splash); runScriptTest(testargs); if (null == testargs[0]) { throw new Exception("testSetup ran with problems"); } } catch (Exception ex) { closeSplash(splash); success &= false; log(-1, ex.getMessage()); popError("Something serious happened! Sikuli not useable!\n" + "Check the error log at " + (logfile == null ? "printout" : logfile)); terminate("Functional test Jython did not work", 1); } } if (getJRuby) { if (hasOptions) { testMethod = "print \"testSetup: JRuby: success\""; } else { testMethod = "Sikulix.testSetup(\"JRuby Scripting\")"; } logPlus(lvl, "JRuby: Trying to run functional test: running script statements via SikuliScript"); splash = showSplash("JRuby Scripting: Trying to run functional test - wait for the result popup", "Running script statements via SikuliScript"); start += 2000; try { String testargs[] = new String[]{"-testSetup", "jruby", testMethod}; closeSplash(splash); runScriptTest(testargs); if (null == testargs[0]) { throw new Exception("testSetup ran with problems"); } } catch (Exception ex) { closeSplash(splash); success &= false; log(-1, "content of returned error's (%s) message:\n%s", ex, ex.getMessage()); popError("Something serious happened! Sikuli not useable!\n" + "Check the error log at " + (logfile == null ? "printout" : logfile)); terminate("Functional test JRuby did not work", 1); } } if (success && Settings.isMac()) { popInfo("You now have the IDE as SikuliX.app\n" + "It is recommended to move SikuliX.app\n" + "to the /Applications folder."); } } //</editor-fold> if (!notests) { splash = showSplash("Setup seems to have ended successfully!", "Detailed information see: " + (logfile == null ? "printout" : logfile)); start += 2000; closeSplash(splash); } logPlus(lvl, "... SikuliX Setup seems to have ended successfully ;-)"); finalCleanup(); System.exit(RunTime.testing ? 1 : 0); } private static String arrayToString(String[] args) { String ret = ""; for (String s : args) { if (s.contains(" ")) { s = "\"" + s + "\""; } ret += s + " "; } return ret; } private static void finalCleanup() { if (hasAPI) jarsList[1] = null; for (int i = (getAPI ? 2 : 1); i < jarsList.length; i++) { if (jarsList[i] != null) { new File(jarsList[i]).delete(); } } FileManager.deleteFileOrFolder(fSetupStuff); } private static void runScriptTest(String[] testargs) { try { Class scriptRunner = Class.forName("org.sikuli.scriptrunner.ScriptingSupport"); Method mGetApplication = scriptRunner.getDeclaredMethod("runscript", new Class[]{String[].class}); mGetApplication.invoke(null, new Object[]{testargs}); } catch (Exception ex) { log(lvl, "runScriptTest: error: %s", ex.getMessage()); } } private static String addSeps(String item) { if (Settings.isWindows()) { return item.replace("/", "\\"); } return item; } private static void checkDownloads() { log(lvl, "checkDownloads: workDir:\n%s", fWorkDir); log(lvl, "checkDownloads: workDirDownloads:\n%s", fDownloadsObsolete); log(lvl, "checkDownloads: downloadsGeneric:\n%s", fDownloadsGeneric); log(lvl, "checkDownloads: downloadsGenericApp:\n%s", fDownloadsGenericApp); downloadsLookfor.put("api", "sikulixsetupAPI-"); downloadsFound.put("api", null); downloadsLookfor.put("ide", "sikulixsetupIDE-"); downloadsFound.put("ide", null); downloadsLookfor.put("win", "sikulixlibswin-"); downloadsFound.put("win", null); downloadsLookfor.put("mac", "sikulixlibsmac-"); downloadsFound.put("mac", null); downloadsLookfor.put("lux", "sikulixlibslux-"); downloadsFound.put("lux", null); downloadsLookfor.put("python", new File(runTime.SikuliJythonMaven).getName()); downloadsFound.put("python", null); downloadsLookfor.put("python25", new File(runTime.SikuliJythonMaven25).getName()); downloadsFound.put("python25", null); downloadsLookfor.put("ruby", "jruby"); downloadsFound.put("ruby", null); downloadsLookfor.put("rubyaddons", "NotYetDefined"); downloadsFound.put("rubyaddons", null); downloadsLookfor.put("tess", "tesseract"); downloadsFound.put("tess", null); String doubleFiles = ""; for (File aFolder : new File[]{ fWorkDir, fDownloadsObsolete, fDownloadsGenericApp, fDownloadsGeneric}) { File[] filesContained = aFolder.listFiles(new FilenameFilter() { List<String> valid = new ArrayList<>(downloadsLookfor.values()); @Override public boolean accept(File dir, String name) { for (String sFile : valid) { if (name.startsWith(sFile)) { return true; } } return false; } }); if (filesContained != null) { for (File aFile : filesContained) { for (String prefix : downloadsLookfor.keySet()) { if (prefix.startsWith("python")) { if (downloadsLookfor.get(prefix).equals(aFile.getName())) { downloadsFound.put(prefix, aFile); } } else if (aFile.getName().startsWith(downloadsLookfor.get(prefix))) { if (null == downloadsFound.get(prefix)) { downloadsFound.put(prefix, aFile); } else { if (aFile.getParentFile().equals(downloadsFound.get(prefix).getParentFile())) { doubleFiles += aFile + "\n"; } } } } } } } for (String prefix : downloadsFound.keySet()) { File fpDownloaded = downloadsFound.get(prefix); if (fpDownloaded != null) { log(lvl, "checkDownloads: found: %s:\n%s", prefix, fpDownloaded); } else { log(lvl, "checkDownloads: not found: %s", prefix); } } if (!doubleFiles.isEmpty()) { popError("The following files are double or even more often found in the\n" + "respective folders setup checks before downloading new artefacts:\n" + doubleFiles + "Please check and take care, that only one version of these files is found.\n" + "Correct the problem and try again"); terminate("double downloaded files"); } } private static boolean createSetupFolder(File fTargetDir) { String projectDir = runTime.fSxProject.getAbsolutePath(); boolean success = true; File fSetup = getProjectJarFile(projectDir, "Setup", "sikulixsetup", "-forsetup.jar"); success &= fSetup != null; File fIDEPlus = getProjectJarFile(projectDir, "SetupIDE", "sikulixsetupIDE", "-forsetup.jar"); success &= fIDEPlus != null; File fAPIPlus = getProjectJarFile(projectDir, "SetupAPI", "sikulixsetupAPI", "-forsetup.jar"); success &= fAPIPlus != null; File fLibsmac = getProjectJarFile(projectDir, "Libsmac", libsMac, ".jar"); success &= fLibsmac != null; File fLibswin = getProjectJarFile(projectDir, "Libswin", libsWin, ".jar"); success &= fLibswin != null; File fLibslux = getProjectJarFile(projectDir, "Libslux", libsLux, ".jar"); success &= fLibslux != null; File fJythonJar = new File(runTime.SikuliJython); if (!noSetup && !fJythonJar.exists()) { log(lvl, "createSetupFolder: missing: " + fJythonJar.getAbsolutePath()); success = false; } File fJythonJar25 = new File(runTime.SikuliJython25); if (!noSetup && !fJythonJar25.exists()) { log(lvl, "createSetupFolder: missing: " + fJythonJar.getAbsolutePath()); fJythonJar25 = null; } File fJrubyJar = new File(runTime.SikuliJRuby); if (!noSetup && !fJrubyJar.exists()) { log(lvl, "createSetupFolder: missing " + fJrubyJar.getAbsolutePath()); success = false; } if (success) { FileManager.resetFolder(fDownloadsGenericApp); success &= FileManager.xcopy(fSetup, new File(fTargetDir, localSetup)); if (success) { for (String sFile : fTargetDir.list()) { if (sFile.contains("sikulixsetup") && sFile.contains("-project") && !sFile.contains(localSetup)) { FileManager.deleteFileOrFolder(new File(fTargetDir, sFile)); } } } success &= FileManager.xcopy(fIDEPlus, new File(fDownloadsGenericApp, downloadIDE)); success &= FileManager.xcopy(fAPIPlus, new File(fDownloadsGenericApp, downloadAPI)); for (File fEntry : new File[]{fLibsmac, fLibswin, fLibslux}) { success &= FileManager.xcopy(fEntry, new File(fDownloadsGenericApp, fEntry.getName())); } if (!noSetup) { success &= FileManager.xcopy(fJythonJar, new File(fDownloadsGeneric, downloadJython)); if (fJythonJar25 != null) { FileManager.xcopy(fJythonJar25, new File(fDownloadsGeneric, downloadJython25)); } success &= FileManager.xcopy(fJrubyJar, new File(fDownloadsGeneric, downloadJRuby)); } //TODO JRubyAddOns String jrubyAddons = "sikulixjrubyaddons-" + runTime.SikuliProjectVersion + "-plain.jar"; File fJRubyAddOns = new File(projectDir, "JRubyAddOns/target/" + jrubyAddons); // success &= FileManager.xcopy(fJRubyAddOns, new File(fDownloadsGeneric, downloadJRubyAddOns)); } return success; } private static File getProjectJarFile(String project, String jarFileDir, String jarFilePre, String jarFileSuf) { String jarFileName = getProjectJarFileName(jarFilePre, jarFileSuf); File fJarFile = new File(project, jarFileDir + "/target/" + jarFileName); if (!fJarFile.exists()) { log(-1, "createSetupFolder: missing: " + fJarFile.getAbsolutePath()); return null; } else { return fJarFile; } } private static String getProjectJarFileName(String jarFilePre, String jarFileSuf) { return String.format("%s-%s%s", jarFilePre, runTime.SikuliProjectVersion, jarFileSuf); } private static boolean handleTempAfter(String temp, String target) { boolean success = true; logPlus(lvl, "renaming sikulixtemp.jar to target jar: %s", new File(target).getName()); FileManager.deleteFileOrFolder("#" + target); success &= !new File(target).exists(); if (success) { success &= (new File(temp)).renameTo(new File(target)); if (!success) { logPlus(lvl, "rename did not work --- trying copy"); try { FileManager.xcopy(new File(temp).getAbsolutePath(), target); success = new File(target).exists(); if (success) { FileManager.deleteFileOrFolder(new File(temp).getAbsolutePath()); success = !new File(temp).exists(); } } catch (IOException ex) { success &= false; } if (!success) { logPlus(-1, "did not work"); terminate(""); } } } return success; } private static boolean getProxy(String pn, String pp) { if (!pn.isEmpty()) { Pattern p = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"); if (p.matcher(pn).matches()) { Settings.proxyIP = pn; } else { Settings.proxyName = pn; } String msgp = String.format("Requested to use this Proxy: %s (%s)", pn, pp); logPlus(lvl, msgp); if (pp.isEmpty()) { popError(String.format("Proxy specification invalid: %s (%s)", pn, pp)); logPlus(-1, "Terminating --- Proxy invalid"); return false; } else { if (!popAsk(msgp)) { logPlus(-1, "Terminating --- User did not accept Proxy: %s %s", pn, pp); return false; } } Settings.proxyPort = pp; return true; } return false; } protected static void helpOption(int option) { String m; String om = ""; m = "\n-------------------- Some Information on this option, that might " + "help to decide, wether to select it ------------------"; switch (option) { case (1): om = "Package 1: You get SikuliX (sikulix.jar) which supports all usages of Sikuli"; // ------------------------------------------------------------- m += "\nIt is recommended for people new to Sikuli to get a feeling about the features"; m += "\n - and those who want to develop Sikuli scripts with the Sikuli IDE"; m += "\n - and those who want to run Sikuli scripts from commandline."; m += "\nDirectly supported scripting languages are Jython and JRuby (you might choose one of them or even both)"; m += "\n\nFor those who know ;-) additionally you can ..."; m += "\n- develop Java programs with Sikuli features in IDE's like Eclipse, NetBeans, ..."; m += "\n- develop in any Java aware scripting language adding Sikuli features in IDE's like Eclipse, NetBeans, ..."; m += "\n\nSpecial INFO for Jython, JRuby and Java developement"; m += "\nIf you want to use standalone Jython/JRuby or want to develop in Java in parallel,"; m += "\nyou should select Package 2 additionally (Option 2)"; m += "\nIn these cases, Package 1 (SikuliX) can be used for image management and for small tests/trials."; if (Settings.isWindows()) { m += "\n\nSpecial info for Windows systems:"; m += "\nThe generated jars can be used out of the box with Java 32-Bit and Java 64-Bit as well."; m += "\nThe Java version is detected at runtime and the native support is switched accordingly."; } // if (Settings.isMac()) { // m += "\n\nSpecial info for Mac systems:"; // m += "\nFinally you will have a Sikuli-IDE.app in the setup working folder."; // m += "\nTo use it, just move it into the Applications folder."; // m += "\nIf you need to run stuff from commandline or want to use Sikuli with Java,"; // m += "\nyou have the following additionally in the setup folder:"; // m += "\nrunIDE: the shellscript to run scripts and"; // m += "\nsikulix.jar: for all other purposes than IDE and running scripts"; // m += "\nMind the above special info about Jython, JRuby and Java developement too."; // } break; case (2): om = "Package 2: To support developement in Java or any Java aware scripting language. you get sikulixapi.jar." + "\nYou might want Package 1 (SikuliX) additionally to use the IDE for managing the images or some trials."; // ------------------------------------------------------------- m += "\nThe content of this package is stripped down to what is needed to develop in Java" + " or any Java aware scripting language \n(no IDE, no bundled script run support for Jython/JRuby)"; m += "\n\nHence this package is not runnable and must be in the class path to use it" + " for developement or at runtime"; m += "\n\nSpecial info for usage with Jython/JRuby: It contains the Sikuli Jython/JRuby API ..." + "\n... and adds itself to Jython/JRuby path at runtime" + "\n... and exports the Sikuli Jython/JRuby modules to the folder Libs at runtime" + "\nthat helps to setup the auto-complete in IDE's like NetBeans, Eclipse ..."; if (Settings.isWindows()) { m += "\n\nSpecial info for Windows systems:"; m += "\nThe generated jars can be used out of the box with Java 32-Bit and Java 64-Bit as well."; m += "\nThe Java version is detected at runtime and the native support is switched accordingly."; } break; case (3): om = "To get the additional Tesseract stuff into your packages to use the OCR engine"; // ------------------------------------------------------------- m += "\nOnly makes sense for Windows and Mac," + "\nsince for Linux the complete install of Tesseract is your job."; m += "\nFeel free to add this to your packages, \n...but be aware of the restrictions, oddities " + "and bugs with the current OCR and text search feature."; m += "\nIt adds more than 10 MB to your jars and the libs folder at runtime." + "\nSo be sure, that you really want to use it!"; m += "\n\nIt is NOT recommended for people new to Sikuli." + "\nYou might add this feature later after having gathered some experiences with Sikuli"; break; case (4): om = "To prepare the selected packages to run on all supported systems"; // ------------------------------------------------------------- m += "\nWith this option NOT selected, the setup process will only add the system specific" + " native stuff \n(Windows: support for both Java 32-Bit and Java 64-Bit is added)"; m += "\n\nSo as a convenience you might select this option to produce jars, that are" + " useable out of the box on Windows, Mac and Linux."; m += "\nThis is possible now, since the usage of Sikuli does not need any system specific" + " preparations any more. \nJust use the package (some restrictions on Linux though)."; m += "\n\nSome scenarios for usages in different system environments:"; m += "\n- download or use the jars from a central network place "; m += "\n- use the jars from a stick or similar mobile medium"; m += "\n- deploying Sikuli apps to be used all over the place"; break; case (5): om = "To try out the experimental remote robot feature"; // ------------------------------------------------------------- m += "\nYou might start the downloaded jar on any system, that is reachable " + "\nby other systems in your network via TCP/IP (hostname or IP-address)." + "\nusing: java -jar sikulixremoterobot.jar" + "\n\nThe server is started and listens on a port (default 50000) for incoming requests" + "\nto use the mouse or keyboard or send back a screenshot." + "\nOn the client side a Sikuli script has to initiate a remote screen with the " + "\nrespective IP-address and port of a running server and on connection success" + "\nthe remote system can be used like a local screen/mouse/keyboard." + "\n\nCurrently all basic operations like find, click, type ... are supported," + "\nbut be aware, that the search ops are done on the local system based on " + "\nscreenshots sent back from the remote system on request." + "\n\nMore information: https://github.com/RaiMan/SikuliX-Remote"; break; } popInfo("asking for option " + option + ": " + om + "\n" + m); } private static String packMessage(String msg) { msg = msg.replace("\n\n", "\n"); msg = msg.replace("\n\n", "\n"); if (msg.startsWith("\n")) { msg = msg.substring(1); } if (msg.endsWith("\n")) { msg = msg.substring(0, msg.length() - 1); } return "--------------------\n" + msg + "\n--------------------"; } private static void popError(String msg) { logPlus(3, "\npopError: " + packMessage(msg)); if (!hasOptions) { JOptionPane.showMessageDialog(null, msg, "SikuliX-Setup: having problems ...", JOptionPane.ERROR_MESSAGE); } } private static void popInfo(String msg) { logPlus(3, "\npopInfo: " + packMessage(msg)); if (!hasOptions) { JOptionPane.showMessageDialog(null, msg, "SikuliX-Setup: info ...", JOptionPane.PLAIN_MESSAGE); } } private static boolean popAsk(String msg) { logPlus(3, "\npopAsk: " + packMessage(msg)); if (hasOptions) { return true; } int ret = JOptionPane.showConfirmDialog(null, msg, "SikuliX-Setup: question ...", JOptionPane.YES_NO_OPTION); if (ret == JOptionPane.CLOSED_OPTION || ret == JOptionPane.NO_OPTION) { return false; } return true; } private static JFrame showSplash(String title, String msg) { if (hasOptions | notests) { return null; } start = (new Date()).getTime(); return new SplashFrame(new String[]{"splash", "# " + title, "#... " + msg}); } private static void closeSplash(JFrame splash) { if (splash == null) { return; } long elapsed = (new Date()).getTime() - start; if (elapsed < 3000) { try { Thread.sleep(3000 - elapsed); } catch (InterruptedException ex) { } } splash.dispose(); } private static File download(String sDir, String tDir, String item, String itemName) { String dlSource; if (item == null) { String[] items = sDir.split("/"); item = items[items.length - 1]; dlSource = sDir; } else { if (!sDir.endsWith("/")) { sDir += "/"; } dlSource = sDir + item; } if (itemName == null) { itemName = item; } String fname = null; if (hasOptions) { logPlus(lvl, "SilentSetup: Downloading: %s", itemName); fname = FileManager.downloadURL(dlSource, tDir, null); } else { JFrame progress = new SplashFrame("download"); fname = FileManager.downloadURL(dlSource, tDir, progress); progress.dispose(); } if (null == fname) { return null; } return new File(fname); } //libDownloaded = takeAlreadyDownloaded(RunFolder, RunFolder/Downloads/ dlDirBuild, dlDirGeneric, libsLux); private static File downloadedAlready(String item, String itemName, boolean isVersioned) { File targetFolder = isVersioned ? fDownloadsGenericApp : fDownloadsGeneric; File artefact = downloadsFound.get(item); File target; if (artefact != null) { target = new File(targetFolder, artefact.getName()); artefact = downloadedAlreadyAsk(artefact, itemName); if (artefact != null && !hasOptions) { if (artefact.getParentFile().equals(isVersioned ? fDownloadsGenericApp : fDownloadsGeneric)) { return artefact; } if (FileManager.xcopy(artefact, target)) { artefact.delete(); artefact = target; } } } return artefact; } private static File downloadedAlreadyAsk(File artefact, String itemName) { if (artefact.exists()) { if (runningWithProject) { return artefact; } if (popAsk("You have for " + itemName + "\n" + artefact.getAbsolutePath() + "\nClick YES, if you want to use this for setup processing\n\n" + "... or click NO, to ignore it and download a fresh copy")) { return artefact; } } return null; } private static boolean copyFromDownloads(File artefact, String item, String jar) { if (artefact == null) { return false; } try { FileManager.xcopy(artefact.getAbsolutePath(), jar); } catch (IOException ex) { log(-1, "Unable to copy from Downloads: %s\n%s", artefact, ex.getMessage()); return false; } logPlus(lvl, "Copied from Downloads: " + item); return true; } private static String getMavenJarPath(String givenItem) { String mPath; String mJar = ""; String itemSuffix = ""; String item = givenItem; if (item.contains("#")) { String[] parts = item.split("#"); item = parts[0]; itemSuffix = "-" + parts[1]; } if (runTime.isVersionRelease()) { // if (itemSuffix.contains("forsetup") || item.contains("sikulixlibs")) { // mPath = runTime.downloadBaseDir; // } else { mPath = String.format("%s%s/%s/", sikulixMavenGroup, item, version); // } mJar = String.format("%s-%s%s.jar", item, version, itemSuffix); } else { String dlMavenSnapshotPath = version + "-SNAPSHOT"; String dlMavenSnapshotXML = "maven-metadata.xml"; String dlMavenSnapshotPrefix = String.format("%s%s/%s/", sikulixMavenGroup, item, dlMavenSnapshotPath); String timeStamp = ""; String buildNumber = ""; mPath = runTime.dlMavenSnapshot + dlMavenSnapshotPrefix; String xml = mPath + dlMavenSnapshotXML; String xmlContent = FileManager.downloadURLtoString(xml); if (xmlContent != null && !xmlContent.isEmpty()) { Matcher m = Pattern.compile("<timestamp>(.*?)</timestamp>").matcher(xmlContent); if (m.find()) { timeStamp = m.group(1); m = Pattern.compile("<buildNumber>(.*?)</buildNumber>").matcher(xmlContent); if (m.find()) { buildNumber = m.group(1); } } } if (!timeStamp.isEmpty() && !buildNumber.isEmpty()) { mJar = String.format("%s-%s-%s-%s%s.jar", item, version, timeStamp, buildNumber, itemSuffix); log(lvl, "getMavenJar: %s", mJar); } else { if (!bequiet) { log(-1, "Maven download: could not get timestamp nor buildnumber for %s from:" + "\n%s\nwith content:\n%s", givenItem, xml, xmlContent); } return null; } } return mPath + mJar; } private static String getMavenJarName(String item) { String fpJar = getMavenJarPath(item); if (fpJar == null) { return null; } return new File(fpJar).getName(); } private static File downloadJarFromMavenSx(String item, String targetDir, String itemName) { String fpJar = getMavenJarPath(item); if (fpJar == null) { return null; } if (runTime.isVersionRelease()) { return downloadJarFromMaven(fpJar, targetDir, itemName); } else { return download(fpJar, targetDir, null, itemName); } } private static File downloadJarFromMaven(String item, String target, String itemName) { if (item.startsWith("http")) { return download(item, target, null, itemName); } else { if (useLocalMavenRepo) { try { URL theFile = new URL("file", null, runTime.SikuliLocalRepo + item); return download(theFile.toExternalForm(), target, null, itemName); } catch (MalformedURLException e) { return null; } } else { return download(runTime.dlMavenRelease + item, target, null, itemName); } } } private static void userTerminated(String msg) { if (!msg.isEmpty()) { logPlus(lvl, msg); } logPlus(lvl, "User requested termination."); System.exit(0); } private static void prepTerminate(String msg) { logPlus(-1, msg); logPlus(-1, "... terminated abnormally :-("); popError("Something serious happened! Sikuli not useable!\n" + "Check the error log at " + (logfile == null ? "printout" : logfile)); finalCleanup(); } private static void terminate(String msg) { prepTerminate(msg); System.exit(0); } private static void terminate(String msg, int ret) { prepTerminate(msg); System.exit(ret); } }