class NetworkRunner extends AbstractRunner {

  private AbortableScriptRunnerWrapper wrapper = new AbortableScriptRunnerWrapper();

  @Override
  protected int doRunScript(String scriptFile, String[] scriptArgs, IRunner.Options options) {

    String scriptUrl = getScriptURL(scriptFile);

    if (null != scriptUrl) {
      File dir = null;

      try {
        dir = Files.createTempDirectory("sikulix").toFile();
        String localFile = FileManager.downloadURL(scriptUrl, dir.getAbsolutePath());
        if (localFile != null) {
          IRunner runner = Runner.getRunner(localFile);
          wrapper.setRunner(runner);
          int retval = runner.runScript(localFile, scriptArgs, options);

          return retval;
        }
      } catch (IOException e) {
        log(-1, "Error creating tmpfile: %s", e.getMessage());
      } finally {
        wrapper.clearRunner();
        if (null != dir) {
          try {
            FileUtils.deleteDirectory(dir);
          } catch (IOException e) {
            log(-1, "Error deleting tmp dir %s: %s", dir, e.getMessage());
          }
        }
      }
    }

    log(-1, "given script location not supported or not valid:\n%s", scriptFile);
    return -1;

  }

  @Override
  public boolean isSupported() {
    return true;
  }

  @Override
  public String getName() {
    return "NetworkRunner";
  }

  @Override
  public boolean canHandle(String identifier) {
    if (identifier != null) {
      int protoSepIndex = identifier.indexOf("://");

      if (protoSepIndex > 0 && protoSepIndex <= 5) {
        String[] parts = identifier.split("://");
        if (parts.length > 1 && !parts[1].isEmpty()) {
          return null != getScriptURL(identifier);
        }
      }
    }

    return false;
  }

  public String resolveRelativeFile(String script) {
    return script;
  }

  private String getScriptURL(String scriptFile) {<FILL_FUNCTION_BODY>}

  @Override
  public String[] getExtensions() {
    // TODO Auto-generated method stub
    return new String[0];
  }

  @Override
  public String getType() {
    return "NET";
  }

  @Override
  public boolean isAbortSupported() {
    return wrapper.isAbortSupported();
  }

  @Override
  protected void doAbort() {
    wrapper.doAbort();
  }

  @Override
	protected void adjustBundlePath(String script, IRunner.Options options) {
	   String identifierParent = script.substring(0, script.lastIndexOf("/"));
	   ImagePath.addHTTP(identifierParent);
	}

	@Override
	protected void resetBundlePath(String script, IRunner.Options options) {
	   String identifierParent = script.substring(0, script.lastIndexOf("/"));
	   ImagePath.removeHTTP(identifierParent);
	}
}

    URL scriptURL;
    try {
      scriptURL = new URL(scriptFile);

      String path = scriptURL.getPath();

      if (path.endsWith("/")) {
        path = path.substring(0, path.length() - 1);
      }

      String basename = FilenameUtils.getBaseName(path);

      String host = scriptURL.getHost();

      if (host.contains("github.com")) {
        host = "https://raw.githubusercontent.com";
        path = path.replace("tree/", "");
      } else {
        host = scriptFile.substring(0, scriptFile.indexOf(path));
      }

      String identifier = host + path;

      for (IRunner runner : Runner.getRunners()) {
        for (String ending : runner.getFileEndings()) {

          String url;

          if (identifier.endsWith(ending)) {
            url = identifier;
          } else {
            url = identifier + "/" + basename + ending;
          }

          if (FileManager.isUrlUseabel(url) > 0) {
            return url;
          }
        }
      }
    } catch (MalformedURLException e) {
      log(-1, "Invalid URL:\n%s", scriptFile);
    }

    return null;
  
<methods>public non-sealed void <init>() ,public final void abort() ,public boolean canHandle(java.lang.String) ,public final boolean canHandleFileEnding(java.lang.String) ,public void checkAndSetConsole() ,public final void close() ,public boolean consoleChecked() ,public void consoleChecked(boolean) ,public final int evalScript(java.lang.String, org.sikuli.support.runner.IRunner.Options) ,public void execAfter(java.lang.String[]) ,public void execBefore(java.lang.String[]) ,public java.lang.String getDefaultExtension() ,public org.sikuli.support.runner.IRunner.EffectiveRunner getEffectiveRunner(java.lang.String) ,public java.lang.String[] getFileEndings() ,public final boolean hasExtension(java.lang.String) ,public final void init(java.lang.String[]) throws org.sikuli.script.SikuliXception,public boolean isAbortSupported() ,public final boolean isAborted() ,public final boolean isReady() ,public final boolean isRunning() ,public boolean isSupported() ,public final void redirect(java.io.PrintStream, java.io.PrintStream) ,public final void reset() ,public final void runLines(java.lang.String, org.sikuli.support.runner.IRunner.Options) ,public final int runScript(java.lang.String, java.lang.String[], org.sikuli.support.runner.IRunner.Options) ,public void setConsole(java.lang.Object) <variables>public static final int NOT_SUPPORTED,private static final java.util.concurrent.ScheduledExecutorService TIMEOUT_EXECUTOR,private static final java.lang.Object WORKER_LOCK,private boolean aborted,static ArrayList<java.lang.String> codeAfter,static ArrayList<java.lang.String> codeBefore,private java.lang.Object console,private boolean consoleChecked,private boolean ready,private boolean running,private static volatile java.lang.Thread worker