@Override
  public void run() {
    if (ctx == null) {
      return;
    }

    if (ctx.getFile() == null) {
      return;
    }

    File root = ctx.getFile();
    if (!root.isDirectory()) {
      logger.debug("root " + root.getAbsolutePath() + " is not directory!");
      return;
    }

    if (!root.exists()) {
      logger.debug("file " + root.getAbsolutePath() + " does not exist!");
      return;
    }

    File[] files = root.listFiles();
    if (files == null) {
      logger.debug("no files for " + root.getAbsolutePath());
      return;
    }

    /**
     * 1/14 | Ejaz Fixed a bug here. If user gives high level folder and file
     * patterns, file watcher did not recurse inside. Added the logic to recurse
     * the folders and find the files, matching the files, to watch!
     *
     */
    for (File file : files) {
      logger.debug("Check file " + file.getAbsolutePath());
      if (!ctx.getJFileWatcherCache().CacheContains(file)) {

        if (file.isDirectory()) {
          logger.debug("Watch folder : " + file.getAbsolutePath());

          JFileWatcherContext ctx2 = ctx.getCopy();
          ctx2.setFile(file);
          ctx2.setPatterns(ctx.getPatterns());

          fileWatcherService.addTask(new JFolderWatcher(ctx2));
        } else {
          // if (regex.matcher(file.getName()).matches()) {
          if (match(file)) {
            JFileWatcherContext ctx2 = ctx.getCopy();
            ctx2.setFile(file);

            logger.debug("Watch file : " + file.getAbsolutePath());

            fileWatcherService.addTask(new JFileWatcher(ctx2));
          }
        }
        ctx.getJFileWatcherCache().CacheAdd(file); // Add to global cache
      }
    }
  }