scripting/src/main/java/com/tersesystems/echopraxia/scripting/ScriptWatchService.java
/**
   * Watches a script, returning a handle that will be "invalid" if the watched directory sees that
   * the file has been touched recently.
   *
   * @param scriptPath the path to the script, must be within the script directory.
   * @param reporter the reporter for an exception.
   * @return the handle to the script.
   */
Watches a script, returning a handle that will be "invalid" if the watched directory sees that
the file has been touched recently.

@param scriptPath the path to the script, must be within the script directory.
@param reporter the reporter for an exception.
@return the handle to the script.
Watches a script returning a handle that will be " invalid " if the watched directory sees that the file has been touched recently . @param scriptPath the path to the script must be within the script directory . @param reporter the reporter for an exception . @return the handle to the script .
public ScriptHandle watchScript(Path scriptPath, Consumer<Throwable> reporter) {
    if (scriptPath == null) {
      String msg = "Null scriptPath";
      throw new ScriptException(msg);
    }
    if (reporter == null) {
      String msg = "Null reporter";
      throw new ScriptException(msg);
    }
    if (!Files.isRegularFile(scriptPath)) {
      String msg = String.format("Path %s is not a file!", scriptPath);
      throw new ScriptException(msg);
    }
    if (!Files.isReadable(scriptPath)) {
      String msg = String.format("Path %s is not readable!", scriptPath);
      throw new ScriptException(msg);
    }
    if (!scriptPath.startsWith(watchedDirectory)) {
      String msg =
          String.format("Path %s is not in watched directory %s", scriptPath, watchedDirectory);
      throw new ScriptException(msg);
    }
    if (!Files.exists(scriptPath)) {
      String msg = String.format("Path %s does not exist!", scriptPath);
      throw new ScriptException(msg);
    }
    AtomicBoolean touched = new AtomicBoolean(false);
    registerPath(scriptPath, touched);
    return new ScriptHandle() {
      @Override
      public void close() throws IOException {
        removeHandle(this);
      }
      @Override
      public boolean isInvalid() {
        return touched.getAndSet(false);
      }
      @Override
      public String script() {
        try {
          final byte[] bytes = Files.readAllBytes(scriptPath);
          return new String(bytes, StandardCharsets.UTF_8);
        } catch (IOException e) {
          throw new ScriptException("Cannot read from " + scriptPath, e);
        }
      }
      @Override
      public String path() {
        return scriptPath.toString();
      }
      @Override
      public void report(Throwable e) {
        reporter.accept(e);
      }
    };
  }
public ScriptHandle watchScript ( Path scriptPath , Consumer < Throwable > reporter ) { if ( scriptPath == null ) { String msg = "Null scriptPath" ; throw new ScriptException ( msg ) ; } if ( reporter == null ) { String msg = "Null reporter" ; throw new ScriptException ( msg ) ; } if ( ! Files . isRegularFile ( scriptPath ) ) { String msg = String . format ( "Path %s is not a file!" , scriptPath ) ; throw new ScriptException ( msg ) ; } if ( ! Files . isReadable ( scriptPath ) ) { String msg = String . format ( "Path %s is not readable!" , scriptPath ) ; throw new ScriptException ( msg ) ; } if ( ! scriptPath . startsWith ( watchedDirectory ) ) { String msg = String . format ( "Path %s is not in watched directory %s" , scriptPath , watchedDirectory ) ; throw new ScriptException ( msg ) ; } if ( ! Files . exists ( scriptPath ) ) { String msg = String . format ( "Path %s does not exist!" , scriptPath ) ; throw new ScriptException ( msg ) ; } AtomicBoolean touched = new AtomicBoolean ( false ) ; registerPath ( scriptPath , touched ) ; return new ScriptHandle ( ) { @ Override public void close ( ) throws IOException { removeHandle ( this ) ; } @ Override public boolean isInvalid ( ) { return touched . getAndSet ( false ) ; } @ Override public String script ( ) { try { final byte [ ] bytes = Files . readAllBytes ( scriptPath ) ; return new String ( bytes , StandardCharsets . UTF_8 ) ; } catch ( IOException e ) { throw new ScriptException ( "Cannot read from " + scriptPath , e ) ; } } @ Override public String path ( ) { return scriptPath . toString ( ) ; } @ Override public void report ( Throwable e ) { reporter . accept ( e ) ; } } ; }
Watches a script, returning a handle that will be "invalid" if the watched directory sees that
 the file has been touched recently.
Watches a script returning a handle that will be " invalid " if the watched directory sees that the file has been touched recently .
// Should this cache internally?  Should only be read on eval...