Package com.darylteo.gradle.watcher.tasks

Source Code of com.darylteo.gradle.watcher.tasks.WatcherTask

package com.darylteo.gradle.watcher.tasks;

import com.darylteo.gradle.watcher.extensions.WatcherExtension;
import com.darylteo.nio.DirectoryChangedSubscriber;
import com.darylteo.nio.DirectoryWatchService;
import com.darylteo.nio.DirectoryWatcher;
import org.gradle.api.DefaultTask;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction;
import org.gradle.tooling.BuildLauncher;
import org.gradle.tooling.ProjectConnection;
import org.gradle.tooling.model.Task;

import java.nio.file.Path;
import java.util.LinkedList;
import java.util.List;

public class WatcherTask extends DefaultTask {
  private WatcherTask that = this;

  private boolean block = true;
  private boolean runImmediately = false;

  private List<Object> tasks = new LinkedList<>();
  private List<String> includes = new LinkedList<>();
  private List<String> excludes = new LinkedList<>();

  private long lastChange;
  private long lastBuild;

  private BuildLauncher builder;
  private Object mutex = new Object();

  public boolean getBlock() {
    return block;
  }

  public void setBlock(boolean block) {
    this.block = block;
  }

  public List<Object> getTasks() {
    return tasks;
  }

  public void setTasks(List<Object> tasks) {
    this.tasks = tasks;
  }

  public List<String> getIncludes() {
    return includes;
  }

  public void setIncludes(List<String> includes) {
    this.includes = includes;
  }

  public List<String> getExcludes() {
    return excludes;
  }

  public void setExcludes(List<String> excludes) {
    this.excludes = excludes;
  }

  public boolean getRunImmediately() {
    return runImmediately;
  }

  public void setRunImmediately(boolean runImmediately) {
    this.runImmediately = runImmediately;
  }

  public WatcherTask() {
    this.includes.add("src/**");
  }

  @TaskAction
  public void action() throws Exception {
    // setup privates
    this.lastChange = 0;
    this.lastBuild = runImmediately ? -1 : 0;

    // setup watcher and connection
    Project project = this.getProject();
    WatcherExtension extension = project.getExtensions().findByType(WatcherExtension.class);

    DirectoryWatchService service = extension.getService();
    ProjectConnection connection = extension.getConnection();

    // setup watcher
    DirectoryWatcher watcher = service.newWatcher(getProject().getProjectDir().getPath());

    for (Object o : this.includes) {
      watcher.include(o.toString());
    }

    for (Object o : this.excludes) {
      watcher.exclude(o.toString());
    }

    // setup builder
    // Note: BuildLauncher only accepts the Task from .model package.
    String[] tasks = generateTaskArguments(project, this.tasks);
    this.builder = connection.newBuild().forTasks(tasks);

    watcher.subscribe(new DirectoryChangedSubscriber() {
      @Override
      public void directoryChanged(DirectoryWatcher watcher, Path entry) {
        synchronized (mutex) {
          WatcherTask.this.lastChange = System.currentTimeMillis();
          mutex.notifyAll();
        }
      }
    });

    scheduleBuild();

    if (this.block) {
      blockTask();
    }
  }

  private String[] generateTaskArguments(Project project, List<Object> tasks) {
    List<String> result = new LinkedList<>();

    for (Object task : tasks) {
      if (task instanceof Task) {
        result.add(((Task) task).getPath());
      } else {
        result.add(String.format("%s:%s", project.getPath(), task));
      }
    }

    return result.toArray(new String[result.size()]);
  }

  private Thread scheduleBuild() {
    final long delay = 1000l;
    final Object lock = new Object();

    Runnable builderThread = new Runnable() {
      public void run() {
        while (true) {
          build();
          waitForChange();
        }
      }

      private void waitForChange() {
        synchronized (that.mutex) {
          try {
            that.mutex.wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }

      private void build() {
        while (that.lastBuild < that.lastChange) {
          that.lastBuild = System.currentTimeMillis();

          try {
            // Errors must be absorbed else the watcher will crap itself.
            builder.run();
          } catch (Throwable e) {
            e.printStackTrace();
          }
        }
      }
    };

    Thread thread = new Thread(builderThread);
    thread.start();

    return thread;
  }

  private void blockTask() {
    Object lock = new Object();

    synchronized (lock) {
      try {
        lock.wait();// block until Ctrl-C
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}
TOP

Related Classes of com.darylteo.gradle.watcher.tasks.WatcherTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.