@Override
  @NotNull
  public VirtualFile[] getRoots(@NotNull final NewVirtualFileSystem fs) {
    final List<VirtualFile> roots = new ArrayList<VirtualFile>();

    myRootsLock.readLock().lock();
    try {
      for (NewVirtualFile root : myRoots.values()) {
        if (root.getFileSystem() == fs) {
          roots.add(root);
        }
      }
    } finally {
      myRootsLock.readLock().unlock();
    }

    return VfsUtilCore.toVirtualFileArray(roots);
  }
  @Override
  @NotNull
  public VirtualFile[] getLocalRoots() {
    List<VirtualFile> roots = ContainerUtil.newSmartList();

    myRootsLock.readLock().lock();
    try {
      for (NewVirtualFile root : myRoots.values()) {
        if (root.isInLocalFileSystem() && !(root.getFileSystem() instanceof TempFileSystem)) {
          roots.add(root);
        }
      }
    } finally {
      myRootsLock.readLock().unlock();
    }

    return VfsUtilCore.toVirtualFileArray(roots);
  }
 private void markContentRootsForRefresh() {
   for (Module module : ModuleManager.getInstance(myProject).getModules()) {
     for (VirtualFile contentRoot : ModuleRootManager.getInstance(module).getContentRoots()) {
       if (contentRoot instanceof NewVirtualFile) {
         ((NewVirtualFile) contentRoot).markDirtyRecursively();
       }
     }
   }
 }
 protected void changeFile(VirtualFile file, final String newText) {
   try {
     if (newText != null) {
       VfsUtil.saveText(file, newText);
     }
     ((NewVirtualFile) file).setTimeStamp(file.getTimeStamp() + 10);
   } catch (IOException e) {
     throw new RuntimeException(e);
   }
 }
  public void testSubst() throws Exception {
    if (!SystemInfo.isWindows) {
      System.err.println("Ignored: Windows required");
      return;
    }

    File targetDir = createTestDir("top");
    File subDir = createTestDir(targetDir, "sub");
    File file = createTestFile(subDir, "test.txt");
    File rootFile = createSubst(targetDir.getAbsolutePath());
    VirtualDirectoryImpl.allowRootAccess(rootFile.getPath());
    VirtualFile vfsRoot = myFileSystem.findFileByIoFile(rootFile);

    try {
      assertNotNull(rootFile.getPath(), vfsRoot);
      File substDir = new File(rootFile, subDir.getName());
      File substFile = new File(substDir, file.getName());
      refresh(targetDir);
      refresh(substDir);

      LocalFileSystem.WatchRequest request = watch(substDir);
      try {
        myAccept = true;
        FileUtil.writeToFile(file, "new content");
        assertEvent(VFileContentChangeEvent.class, substFile.getAbsolutePath());

        LocalFileSystem.WatchRequest request2 = watch(targetDir);
        try {
          myAccept = true;
          FileUtil.delete(file);
          assertEvent(VFileDeleteEvent.class, file.getAbsolutePath(), substFile.getAbsolutePath());
        } finally {
          unwatch(request2);
        }

        myAccept = true;
        FileUtil.writeToFile(file, "re-creation");
        assertEvent(VFileCreateEvent.class, substFile.getAbsolutePath());
      } finally {
        unwatch(request);
      }
    } finally {
      delete(targetDir);
      IoTestUtil.deleteSubst(rootFile.getPath());
      if (vfsRoot != null) {
        ((NewVirtualFile) vfsRoot).markDirty();
        myFileSystem.refresh(false);
      }
      VirtualDirectoryImpl.disallowRootAccess(rootFile.getPath());
    }
  }
  public static void markDirtyAndRefresh(
      boolean async, boolean recursive, boolean loadChildren, VirtualFile... files) {
    List<VirtualFile> list = ContainerUtil.filter(Condition.NOT_NULL, files);
    if (list.isEmpty()) {
      return;
    }

    for (VirtualFile file : list) {
      if (loadChildren) {
        file.getChildren();
      }

      if (file instanceof NewVirtualFile) {
        if (recursive) {
          ((NewVirtualFile) file).markDirtyRecursively();
        } else {
          ((NewVirtualFile) file).markDirty();
        }
      }
    }

    LocalFileSystem.getInstance().refreshFiles(list, async, recursive, null);
  }
  public static void doTestInterruptedRefresh(@NotNull File top) throws Exception {
    File sub = IoTestUtil.createTestDir(top, "sub");
    File subSub = IoTestUtil.createTestDir(sub, "sub_sub");
    File file1 = IoTestUtil.createTestFile(sub, "sub_file_to_stop_at");
    File file2 = IoTestUtil.createTestFile(subSub, "sub_sub_file");
    LocalFileSystem lfs = LocalFileSystem.getInstance();
    NewVirtualFile topDir = (NewVirtualFile) lfs.refreshAndFindFileByIoFile(top);
    assertNotNull(topDir);
    NewVirtualFile subFile1 = (NewVirtualFile) lfs.refreshAndFindFileByIoFile(file1);
    assertNotNull(subFile1);
    NewVirtualFile subFile2 = (NewVirtualFile) lfs.refreshAndFindFileByIoFile(file2);
    assertNotNull(subFile2);
    topDir.refresh(false, true);
    assertFalse(topDir.isDirty());
    assertFalse(subFile1.isDirty());
    assertFalse(subFile2.isDirty());

    try {
      subFile1.markDirty();
      subFile2.markDirty();
      RefreshWorker.setCancellingCondition(
          new Function<VirtualFile, Boolean>() {
            @Override
            public Boolean fun(VirtualFile file) {
              return "sub_file_to_stop_at".equals(file.getName());
            }
          });
      topDir.refresh(false, true);
      // should remain dirty after aborted refresh
      assertTrue(subFile1.isDirty());
      assertTrue(subFile2.isDirty());

      RefreshWorker.setCancellingCondition(null);
      topDir.refresh(false, true);
      assertFalse(topDir.isDirty());
      assertFalse(subFile1.isDirty());
      assertFalse(subFile2.isDirty());
    } finally {
      RefreshWorker.setCancellingCondition(null);
    }
  }
  public static void doTestPartialRefresh(@NotNull File top) throws IOException {
    File sub = IoTestUtil.createTestDir(top, "sub");
    File file = IoTestUtil.createTestFile(top, "sub.txt");
    LocalFileSystem lfs = LocalFileSystem.getInstance();
    NewVirtualFile topDir = (NewVirtualFile) lfs.refreshAndFindFileByIoFile(top);
    assertNotNull(topDir);
    NewVirtualFile subDir = (NewVirtualFile) lfs.refreshAndFindFileByIoFile(sub);
    assertNotNull(subDir);
    NewVirtualFile subFile = (NewVirtualFile) lfs.refreshAndFindFileByIoFile(file);
    assertNotNull(subFile);
    topDir.refresh(false, true);
    assertFalse(topDir.isDirty());
    assertFalse(subDir.isDirty());
    assertFalse(subFile.isDirty());

    subFile.markDirty();
    subDir.markDirty();
    assertTrue(topDir.isDirty());
    assertTrue(subFile.isDirty());
    assertTrue(subDir.isDirty());

    topDir.refresh(false, false);
    assertFalse(subFile.isDirty());
    assertTrue(subDir.isDirty()); // should stay unvisited after non-recursive refresh

    topDir.refresh(false, true);
    assertFalse(topDir.isDirty());
    assertFalse(subFile.isDirty());
    assertFalse(subDir.isDirty());
  }
  public void scan() {
    final NewVirtualFile root = (NewVirtualFile) myRefreshRoot;
    NewVirtualFileSystem delegate = root.getFileSystem();
    if (root.isDirty() && !delegate.exists(root)) {
      scheduleDeletion(root);
      root.markClean();
    } else {
      if (delegate.getProtocol().equals(LocalFileSystem.PROTOCOL)
          && root.isDirectory()
          && Registry.is("filesystem.useNative")) {

        if (SystemInfo.isWindows && Win32LocalFileSystem.isAvailable()) {
          delegate = Win32LocalFileSystem.getWin32Instance();
        }
      }

      final PersistentFS persistence = (PersistentFS) ManagingFS.getInstance();

      while (!myRefreshQueue.isEmpty()) {
        final VirtualFileSystemEntry file = (VirtualFileSystemEntry) myRefreshQueue.pullFirst();
        if (!file.isDirty()) continue;

        if (file.isDirectory()) {
          VirtualDirectoryImpl dir = (VirtualDirectoryImpl) file;
          final boolean fullSync = dir.allChildrenLoaded();
          if (fullSync) {
            Set<String> currentNames = new HashSet<String>(Arrays.asList(persistence.list(file)));
            Set<String> uptodateNames =
                new HashSet<String>(Arrays.asList(VfsUtil.filterNames(delegate.list(file))));

            Set<String> newNames = new HashSet<String>(uptodateNames);
            newNames.removeAll(currentNames);

            Set<String> deletedNames = new HashSet<String>(currentNames);
            deletedNames.removeAll(uptodateNames);

            for (String name : deletedNames) {
              scheduleDeletion(file.findChild(name));
            }

            for (String name : newNames) {
              boolean isDirectory = delegate.isDirectory(new FakeVirtualFile(file, name));
              scheduleCreation(file, name, isDirectory);
            }

            for (VirtualFile child : file.getChildren()) {
              if (!deletedNames.contains(child.getName())) {
                scheduleChildRefresh(file, child, delegate);
              }
            }
          } else {
            for (VirtualFile child : file.getCachedChildren()) {
              if (delegate.exists(child)) {
                scheduleChildRefresh(file, child, delegate);
              } else {
                scheduleDeletion(child);
              }
            }

            final List<String> names = dir.getSuspiciousNames();
            for (String name : names) {
              if (name.length() == 0) continue;

              final VirtualFile fake = new FakeVirtualFile(file, name);
              if (delegate.exists(fake)) {
                scheduleCreation(file, name, delegate.isDirectory(fake));
              }
            }
          }
        } else {
          long currentTimestamp = persistence.getTimeStamp(file);
          long updtodateTimestamp = delegate.getTimeStamp(file);

          if (currentTimestamp != updtodateTimestamp) {
            scheduleUpdateContent(file);
          }
        }

        boolean currentWritable = persistence.isWritable(file);
        boolean uptodateWritable = delegate.isWritable(file);

        if (currentWritable != uptodateWritable) {
          scheduleWritableAttributeChange(file, currentWritable, uptodateWritable);
        }

        file.markClean();
      }
    }
  }