/**
  * Executes the jythonscript
  *
  * @param pyFile The file containing the script
  * @param imagePath The directory containing the images
  * @param argv The arguments passed by the --args parameter
  * @param forIDE
  * @return The exitcode
  */
 @Override
 public int runScript(File pyFile, File imagePath, String[] argv, String[] forIDE) {
   if (null == pyFile) {
     // run the Python statements from argv (special for setup functional test)
     executeScriptHeader(null);
     log(lvl, "runPython: running statements");
     try {
       for (String e : argv) {
         interpreter.exec(e);
       }
     } catch (Exception ex) {
       log(-1, "runPython: raised: %s", ex.getMessage());
       return -1;
     }
     return 0;
   }
   isFromIDE = !(forIDE == null);
   if (isFromIDE && forIDE.length > 1 && forIDE[0] != null) {
     isCompileOnly = forIDE[0].toUpperCase().equals(COMPILE_ONLY);
   }
   pyFile = new File(pyFile.getAbsolutePath());
   fillSysArgv(pyFile, argv);
   if (forIDE == null) {
     executeScriptHeader(new String[] {pyFile.getParent(), pyFile.getParentFile().getParent()});
   } else {
     executeScriptHeader(new String[] {forIDE[0]});
   }
   int exitCode = 0;
   if (isFromIDE) {
     exitCode = runPython(pyFile, null, forIDE);
   } else {
     exitCode = runPython(pyFile, null, new String[] {pyFile.getParentFile().getAbsolutePath()});
   }
   log(lvl + 1, "runScript: at exit: path:");
   for (Object p : interpreter.getSystemState().path.toArray()) {
     log(lvl + 1, "runScript: " + p.toString());
   }
   log(lvl + 1, "runScript: at exit: --- end ---");
   return exitCode;
 }
  /**
   * Executes the defined header for the jython script.
   *
   * @param syspaths List of all syspath entries
   */
  private void executeScriptHeader(String[] syspaths) {
    // TODO implement compile only
    if (isCompileOnly) {
      return;
    }
    PyList jypath = interpreter.getSystemState().path;
    int jypathLength = jypath.__len__();
    boolean contained = false;
    for (int i = 0; i < jypathLength; i++) {
      if (FileManager.pathEquals((String) jypath.get(0), sikuliLibPath)) {
        contained = true;
        break;
      }
    }
    if (!contained) {
      log(lvl, "executeScriptHeader: adding Jython Lib path to sys.path\n" + sikuliLibPath);
      String[] jypathNew = new String[jypathLength + 1];
      jypathNew[0] = (String) jypath.get(0);
      log(lvl + 1, "executeScriptHeader: before: 0: %s", jypath.get(0));
      for (int i = 1; i < jypathLength; i++) {
        log(lvl + 1, "executeScriptHeader: before: %d: %s", i, jypath.get(i));
        jypathNew[i + 1] = (String) jypath.get(i);
      }
      for (int i = 0; i < jypathLength; i++) {
        jypath.set(i, jypathNew[i]);
      }
      jypath.add(jypathNew[jypathNew.length - 1]);
      for (int i = 0; i < jypathNew.length; i++) {
        log(lvl + 1, "executeScriptHeader: after: %d: %s", i, jypath.get(i));
      }
    }
    if (savedpathlen == 0) {
      savedpathlen = interpreter.getSystemState().path.size();
      log(lvl + 1, "executeScriptHeader: saved sys.path: %d", savedpathlen);
    } else if (interpreter.getSystemState().path.size() > savedpathlen) {
      interpreter
          .getSystemState()
          .path
          .remove(savedpathlen, interpreter.getSystemState().path.size());
    }
    log(lvl + 1, "executeScriptHeader: at entry: path:");
    for (Object p : interpreter.getSystemState().path.toArray()) {
      log(lvl + 1, p.toString());
    }
    log(lvl + 1, "executeScriptHeader: at entry: --- end ---");

    if (syspaths != null) {
      for (String syspath : syspaths) {
        jypath.add(FileManager.slashify(syspath, false));
      }
    }

    for (String line : SCRIPT_HEADER) {
      log(lvl + 1, "executeScriptHeader: PyInit: %s", line);
      interpreter.exec(line);
    }
    if (codeBefore != null) {
      for (String line : codeBefore) {
        interpreter.exec(line);
      }
    }
  }