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()); } }
@Override protected void setUp() throws Exception { LOG.debug("================== setting up " + getName() + " =================="); super.setUp(); myFileSystem = LocalFileSystem.getInstance(); assertNotNull(myFileSystem); myWatcher = ((LocalFileSystemImpl) myFileSystem).getFileWatcher(); assertNotNull(myWatcher); assertFalse(myWatcher.isOperational()); myWatcher.startup(myNotifier); assertTrue(myWatcher.isOperational()); myAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, getProject()); myTimeout = NATIVE_PROCESS_DELAY; myConnection = ApplicationManager.getApplication().getMessageBus().connect(); myConnection.subscribe( VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() { @Override public void after(@NotNull List<? extends VFileEvent> events) { synchronized (myEvents) { myEvents.addAll(events); } } }); ((LocalFileSystemImpl) myFileSystem).cleanupForNextTest(); LOG = FileWatcher.getLog(); LOG.debug("================== setting up " + getName() + " =================="); }
private List<VFileEvent> getEvents(String msg, @Nullable Runnable action) { LOG.debug("** waiting for " + msg); myAccept = true; if (action != null) { action.run(); } int timeout = myTimeout; try { synchronized (myWaiter) { //noinspection WaitNotInLoop myWaiter.wait(timeout); } } catch (InterruptedException e) { LOG.warn(e); } LOG.debug("** waited for " + timeout); myFileSystem.refresh(false); ArrayList<VFileEvent> result; synchronized (myEvents) { result = new ArrayList<VFileEvent>(myEvents); myEvents.clear(); } LOG.debug("** events: " + result.size()); return result; }
@NotNull private VirtualFilePointer create( @Nullable VirtualFile file, @NotNull String url, @NotNull final Disposable parentDisposable, @Nullable VirtualFilePointerListener listener) { String protocol; VirtualFileSystem fileSystem; if (file == null) { protocol = VirtualFileManager.extractProtocol(url); fileSystem = myVirtualFileManager.getFileSystem(protocol); } else { protocol = null; fileSystem = file.getFileSystem(); } if (fileSystem == TempFileSystem.getInstance()) { // for tests, recreate always since VirtualFile found = fileSystem == null ? null : file != null ? file : VirtualFileManager.getInstance().findFileByUrl(url); return new IdentityVirtualFilePointer(found, url); } if (fileSystem != LocalFileSystem.getInstance() && fileSystem != JarFileSystem.getInstance()) { // we are unable to track alien file systems for now VirtualFile found = fileSystem == null ? null : file != null ? file : VirtualFileManager.getInstance().findFileByUrl(url); // if file is null, this pointer will never be alive return getOrCreateIdentity(url, found); } String path; if (file == null) { path = VirtualFileManager.extractPath(url); path = cleanupPath(path, protocol); url = VirtualFileManager.constructUrl(protocol, path); } else { path = file.getPath(); // url has come from VirtualFile.getUrl() and is good enough } VirtualFilePointerImpl pointer = getOrCreate(file, url, parentDisposable, listener, path); int newCount = pointer.incrementUsageCount(); if (newCount == 1) { Disposer.register(parentDisposable, pointer); } else { // already registered register(parentDisposable, pointer); } return pointer; }
private void delete(File file) throws IOException { VirtualFile vFile = myFileSystem.findFileByIoFile(file); if (vFile != null) { AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(getClass()); try { vFile.delete(this); } finally { token.finish(); } } if (file.exists()) { FileUtil.delete(file); } }
private VirtualFile refresh(File file) { VirtualFile vFile = myFileSystem.refreshAndFindFileByIoFile(file); assertNotNull(file.toString(), vFile); VfsUtilCore.visitChildrenRecursively( vFile, new VirtualFileVisitor() { @Override public boolean visitFile(@NotNull VirtualFile file) { file.getChildren(); return true; } }); return vFile; }
@Override @Nullable public VirtualFileSystemEntry findRoot( @NotNull String basePath, @NotNull NewVirtualFileSystem fs) { if (basePath.isEmpty()) { LOG.error("Invalid root, fs=" + fs); return null; } String rootUrl = normalizeRootUrl(basePath, fs); myRootsLock.readLock().lock(); try { VirtualFileSystemEntry root = myRoots.get(rootUrl); if (root != null) return root; } finally { myRootsLock.readLock().unlock(); } final VirtualFileSystemEntry newRoot; int rootId = FSRecords.findRootRecord(rootUrl); VfsData.Segment segment = VfsData.getSegment(rootId, true); VfsData.DirectoryData directoryData = new VfsData.DirectoryData(); if (fs instanceof ArchiveFileSystem) { String parentPath = basePath.substring(0, basePath.indexOf(ArchiveFileSystem.ARCHIVE_SEPARATOR)); VirtualFile parentFile = LocalFileSystem.getInstance().findFileByPath(parentPath); if (parentFile == null) return null; FileType type = FileTypeRegistry.getInstance().getFileTypeByFileName(parentFile.getName()); if (!(type instanceof ArchiveFileType)) return null; newRoot = new ArchiveRoot(fs, rootId, segment, directoryData, parentFile); } else { newRoot = new FsRoot(fs, rootId, segment, directoryData, basePath); } FileAttributes attributes = fs.getAttributes( new StubVirtualFile() { @NotNull @Override public String getPath() { return newRoot.getPath(); } @Nullable @Override public VirtualFile getParent() { return null; } }); if (attributes == null || !attributes.isDirectory()) { return null; } boolean mark = false; myRootsLock.writeLock().lock(); try { VirtualFileSystemEntry root = myRoots.get(rootUrl); if (root != null) return root; VfsData.initFile(rootId, segment, -1, directoryData); mark = writeAttributesToRecord(rootId, 0, newRoot, fs, attributes); myRoots.put(rootUrl, newRoot); myRootsById.put(rootId, newRoot); } finally { myRootsLock.writeLock().unlock(); } if (!mark && attributes.lastModified != FSRecords.getTimestamp(rootId)) { newRoot.markDirtyRecursively(); } LOG.assertTrue( rootId == newRoot.getId(), "root=" + newRoot + " expected=" + rootId + " actual=" + newRoot.getId()); return newRoot; }
@Override @Nullable public VirtualFileSystemEntry findRoot( @NotNull String basePath, @NotNull NewVirtualFileSystem fs) { String rootUrl = normalizeRootUrl(basePath, fs); boolean isFakeRoot = basePath.isEmpty(); VirtualFileSystemEntry root; myRootsLock.readLock().lock(); try { root = isFakeRoot ? mySuperRoot : myRoots.get(rootUrl); if (root != null) return root; } finally { myRootsLock.readLock().unlock(); } myRootsLock.writeLock().lock(); try { root = isFakeRoot ? mySuperRoot : myRoots.get(rootUrl); if (root != null) return root; int rootId = FSRecords.findRootRecord(rootUrl); root = myRootsById.get(rootId); if (root != null) return root; if (isFakeRoot) { // fake super-root root = new FakeRoot(fs, rootId); } else if (fs instanceof JarFileSystem) { // optimization: for jar roots do not store base path in the myName field, use local FS // file's getPath() String parentPath = basePath.substring(0, basePath.indexOf(JarFileSystem.JAR_SEPARATOR)); VirtualFile parentLocalFile = LocalFileSystem.getInstance().findFileByPath(parentPath); if (parentLocalFile == null) return null; // check one more time since the findFileByPath could have created the root (by reentering // the findRoot) root = myRoots.get(rootUrl); if (root != null) return root; root = myRootsById.get(rootId); if (root != null) return root; root = new JarRoot(fs, rootId, parentLocalFile); } else { root = new FsRoot(fs, rootId, basePath); } if (isFakeRoot) { mySuperRoot = root; } else { FileAttributes attributes = fs.getAttributes(root); if (attributes == null || !attributes.isDirectory()) { return null; } final boolean newRoot = writeAttributesToRecord(rootId, 0, root, fs, attributes); if (!newRoot && attributes.lastModified != FSRecords.getTimestamp(rootId)) { root.markDirtyRecursively(); } myRoots.put(rootUrl, root); myRootsById.put(rootId, root); if (rootId != root.getId()) throw new AssertionError(); } return root; } finally { myRootsLock.writeLock().unlock(); } }