title: How to make sure all files uploaded via SFTP in watched directory are ok to use via Java7?
body: <p>I'm using <code>WatchService</code> to monitor a directory. Another third party will upload large CSV files to that directory via SFTP. I have to wait until all the files are finished to start processing the files. </p>
  
  <p>My trouble right now is that SFTP creates the file as soon as the uploading starts I get <code>ENTRY_CREATE</code> and continuously get <code>ENTRY_MODIFY</code> until the file is done. Is there anyway to tell if the file is actually done. </p>
  
  <p>This is the code I use which I got it from Java Documentation</p>
  
  <pre><code>public class WatchDir {
  
  private final WatchService watcher;
  private final Map&lt;WatchKey, Path&gt; keys;
  private final boolean recursive;
  private boolean trace = false;
  
  @SuppressWarnings("unchecked")
  static &lt;T&gt; WatchEvent&lt;T&gt; cast(WatchEvent&lt;?&gt; event) {
      return (WatchEvent&lt;T&gt;) event;
  }
  
  /**
   * Register the given directory with the WatchService
   */
  private void register(Path dir) throws IOException {
      WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
      if (trace) {
          Path prev = keys.get(key);
          if (prev == null) {
              System.out.format("register: %s\n", dir);
          } else {
              if (!dir.equals(prev)) {
                  System.out.format("update: %s -&gt; %s\n", prev, dir);
              }
          }
      }
      keys.put(key, dir);
  }
  
  /**
   * Register the given directory, and all its sub-directories, with the
   * WatchService.
   */
  private void registerAll(final Path start) throws IOException {
      // register directory and sub-directories
      Files.walkFileTree(start, new SimpleFileVisitor&lt;Path&gt;() {
          @Override
          public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                  throws IOException {
              register(dir);
              return FileVisitResult.CONTINUE;
          }
      });
  }
  
  /**
   * Creates a WatchService and registers the given directory
   */
  WatchDir(Path dir, boolean recursive) throws IOException {
      this.watcher = FileSystems.getDefault().newWatchService();
      this.keys = new HashMap&lt;WatchKey, Path&gt;();
      this.recursive = recursive;
  
      if (recursive) {
          System.out.format("Scanning %s ...\n", dir);
          registerAll(dir);
          System.out.println("Done.");
      } else {
          register(dir);
      }
  
      // enable trace after initial registration
      this.trace = true;
  }
  
  /**
   * Process all events for keys queued to the watcher
   */
  void processEvents() {
      for (; ; ) {
  
          // wait for key to be signalled
          WatchKey key;
          try {
              key = watcher.take();
          } catch (InterruptedException x) {
              return;
          }
  
          Path dir = keys.get(key);
          if (dir == null) {
              System.err.println("WatchKey not recognized!!");
              continue;
          }
  
          for (WatchEvent&lt;?&gt; event : key.pollEvents()) {
              WatchEvent.Kind kind = event.kind();
  
              // TBD - provide example of how OVERFLOW event is handled
              if (kind == OVERFLOW) {
                  continue;
              }
  
              // Context for directory entry event is the file name of entry
              WatchEvent&lt;Path&gt; ev = cast(event);
              Path name = ev.context();
              Path child = dir.resolve(name);
  
              // print out event
              System.out.format("%s: %s\n", event.kind().name(), child);
  
              // if directory is created, and watching recursively, then
              // register it and its sub-directories
              if (recursive &amp;&amp; (kind == ENTRY_CREATE)) {
                  try {
                      if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
                          registerAll(child);
                      }
                  } catch (IOException x) {
                      // ignore to keep sample readbale
                  }
              }
          }
  
          // reset key and remove from set if directory no longer accessible
          boolean valid = key.reset();
          if (!valid) {
              keys.remove(key);
  
              // all directories are inaccessible
              if (keys.isEmpty()) {
                  break;
              }
          }
      }
  }
  
  static void usage() {
      System.err.println("usage: java WatchDir [-r] dir");
      System.exit(-1);
  }
  
  public static void main(String[] args) throws IOException {
      // parse arguments
      if (args.length == 0 || args.length &gt; 2)
          usage();
      boolean recursive = false;
      int dirArg = 0;
      if (args[0].equals("-r")) {
          if (args.length &lt; 2)
              usage();
          recursive = true;
          dirArg++;
      }
  
      // register directory and process its events
      Path dir = Paths.get(args[dirArg]);
      new WatchDir(dir, recursive).processEvents();
  }
  </code></pre>
  
  <p>}</p>