public DirectoryDescendingFileFinderImpl(File root, FilenameFilter filter, boolean canonical)
     throws IOException {
   if (!root.isDirectory())
     throw new IllegalArgumentException(root.getName() + " is not a directory.");
   this.filter = filter;
   this.canonical = canonical;
   blossomDirectory(root);
   while (files.empty() && !direx.empty()) blossomDirectory((File) direx.pop());
 }
 private void blossomDirectory(File dir) throws IOException {
   // System.out.println(">> blossomDirectory() on " + dir.getPath());
   String canonicalPath = dir.getCanonicalPath();
   String[] listing = (filter == null ? dir.list() : dir.list(filter));
   for (int i = listing.length; --i >= 0; ) {
     // System.out.println(">> listing: " + listing[i]);
     if (filter == null || filter.accept(dir, listing[i])) {
       String name = (canonical ? canonicalPath : dir.getPath()) + File.separator + listing[i];
       File file = new File(name);
       // System.out.println(">> parent: " + dir.getName());
       // System.out.println(">> created file: " + file.getPath());
       if (file.isFile()) files.push(file);
       else // dir
       {
         if (!markedDirex.containsKey(file.getCanonicalPath())) direx.push(file);
       }
     }
   }
   markedDirex.put(canonicalPath, dummy);
 }
 public File nextFile() throws IOException {
   if (files.empty()) throw new NoSuchElementException();
   File out = (File) files.pop();
   while (files.empty() && !direx.empty()) blossomDirectory((File) direx.pop());
   return out;
 }
 public boolean hasMoreFiles() {
   return !files.empty();
 }