Skip to content

Instantly share code, notes, and snippets.

@themillhousegroup
Last active May 21, 2018 20:55

Revisions

  1. themillhousegroup revised this gist Mar 20, 2014. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions DirectoryFileCreationWatcher
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@

    class DirectoryFileCreationWatcher(directoryToWatch:Path) {
    import java.nio.file._
    import java.nio.file.StandardWatchEventKinds._
    @@ -84,7 +83,7 @@ class DirectoryFileCreationWatcherSpec extends Specification {

    "not notify the caller until the dir contains a matching file - exact match on file" in {
    val future = new DirectoryFileCreationWatcher(watchedDir).awaitFile{ path =>
    path.toFile.getAbsolutePath.endsWith(testFileName)
    path.endsWith(testFileName)
    }

    future.isCompleted must beFalse
  2. themillhousegroup created this gist Mar 20, 2014.
    104 changes: 104 additions & 0 deletions DirectoryFileCreationWatcher
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,104 @@

    class DirectoryFileCreationWatcher(directoryToWatch:Path) {
    import java.nio.file._
    import java.nio.file.StandardWatchEventKinds._
    import scala.concurrent.ExecutionContext.Implicits.global
    import scala.collection.JavaConversions._

    val watcher = FileSystems.getDefault.newWatchService

    // Work properly on Mac:
    //http://stackoverflow.com/questions/9588737/is-java-7-watchservice-slow-for-anyone-else
    val kinds:Array[Kind[_]] = Seq(StandardWatchEventKinds.ENTRY_CREATE).toArray
    directoryToWatch.register(watcher, kinds, SensitivityWatchEventModifier.HIGH.asInstanceOf[WatchEvent.Modifier])

    /**
    *
    * @param pathMatcher a function that returns true if this is the file we're looking for
    * @return a Future holding a Path that represents the directory in its "new" state
    */
    def awaitFile( pathMatcher: Path => Boolean):Future[Path] = Future[Path] {
    var foundMatch = false
    while (!foundMatch) {
    val watchKey = watcher.take // Blocks
    val events = watchKey.pollEvents
    foundMatch = events.exists { event =>
    val wep = event.asInstanceOf[WatchEvent[Path]]
    pathMatcher(wep.context)
    }
    watchKey.reset
    }
    directoryToWatch
    }
    }

    class DirectoryFileCreationWatcherSpec extends Specification {
    import java.nio.file._
    import scala.concurrent.ExecutionContext.Implicits.global
    import scala.collection.JavaConversions._

    isolated
    "DirectoryFileCreationWatcher" should {
    val watchedDir = Files.createTempDirectory("watchedDir")
    val testFileName = "testFile.txt"
    val secondTestFileName = "testFile2.txt"
    val waitToNoticeChange = 2000
    val noticeDelay = scala.concurrent.duration.FiniteDuration(waitToNoticeChange, "millis")
    val halfSecond = scala.concurrent.duration.FiniteDuration(500, "millis")

    def addFileToWatchedDir(fileName:String):java.io.File = {
    val f = new java.io.File(watchedDir.toFile, fileName)
    f.createNewFile
    println(s"added file ${f.getAbsolutePath}")
    f
    }

    "not notify the caller until the dir contains a matching file - any file" in {
    val future = new DirectoryFileCreationWatcher(watchedDir).awaitFile{ path =>
    true
    }

    future.isCompleted must beFalse

    addFileToWatchedDir(testFileName)

    Thread.sleep(waitToNoticeChange)
    future.isCompleted must beTrue
    }

    "notify the caller with the new contents of the dir - for any file" in {
    val future = new DirectoryFileCreationWatcher(watchedDir).awaitFile{ path =>
    true
    }

    watchedDir.toFile.list.contains(testFileName) must beFalse

    addFileToWatchedDir(testFileName)

    future.map { dirPath =>
    println(s"dirPath: ${dirPath.toFile.list.mkString}" )
    dirPath.toFile.list.contains(testFileName)
    } must beTrue.await(timeout = halfSecond, retries=4)
    }


    "not notify the caller until the dir contains a matching file - exact match on file" in {
    val future = new DirectoryFileCreationWatcher(watchedDir).awaitFile{ path =>
    path.toFile.getAbsolutePath.endsWith(testFileName)
    }

    future.isCompleted must beFalse

    addFileToWatchedDir(secondTestFileName)

    Thread.sleep(waitToNoticeChange)
    future.isCompleted must beFalse


    addFileToWatchedDir(testFileName)
    Thread.sleep(waitToNoticeChange)

    future.isCompleted must beTrue

    }
    }