2 * Copyright 2000-2011 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.openapi.vfs.newvfs.persistent;
18 import com.intellij.openapi.vfs.VfsUtil;
19 import com.intellij.openapi.vfs.VirtualFile;
20 import com.intellij.openapi.vfs.newvfs.ManagingFS;
21 import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
22 import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem;
23 import com.intellij.openapi.vfs.newvfs.events.*;
24 import com.intellij.openapi.vfs.newvfs.impl.FakeVirtualFile;
25 import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl;
26 import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
27 import com.intellij.util.containers.Queue;
28 import org.jetbrains.annotations.NotNull;
35 public class RefreshWorker {
36 private final VirtualFile myRefreshRoot;
37 private final boolean myIsRecursive;
38 private final Queue<VirtualFile> myRefreshQueue = new Queue<VirtualFile>(100);
40 private final List<VFileEvent> myEvents = new ArrayList<VFileEvent>();
42 public RefreshWorker(final VirtualFile refreshRoot, final boolean isRecursive) {
43 myRefreshRoot = refreshRoot;
44 myIsRecursive = isRecursive;
45 myRefreshQueue.addLast(refreshRoot);
49 final NewVirtualFile root = (NewVirtualFile)myRefreshRoot;
50 NewVirtualFileSystem delegate = root.getFileSystem();
51 int attributes = delegate.getBooleanAttributes(root, NewVirtualFileSystem.BA_EXISTS | NewVirtualFileSystem.BA_DIRECTORY);
53 if (root.isDirty() && (attributes & NewVirtualFileSystem.BA_EXISTS) == 0) {
54 scheduleDeletion(root);
58 boolean isDir = (attributes & NewVirtualFileSystem.BA_DIRECTORY) != 0;
60 delegate = PersistentFS.replaceWithNativeFS(delegate);
63 final PersistentFS persistence = (PersistentFS)ManagingFS.getInstance();
65 while (!myRefreshQueue.isEmpty()) {
66 final VirtualFileSystemEntry file = (VirtualFileSystemEntry)myRefreshQueue.pullFirst();
67 if (!file.isDirty()) continue;
69 if (file.isDirectory()) {
70 VirtualDirectoryImpl dir = (VirtualDirectoryImpl)file;
71 final boolean fullSync = dir.allChildrenLoaded();
73 Set<String> currentNames = new HashSet<String>(Arrays.asList(persistence.list(file)));
74 Set<String> upToDateNames = new HashSet<String>(Arrays.asList(VfsUtil.filterNames(delegate.list(file))));
76 Set<String> newNames = new HashSet<String>(upToDateNames);
77 newNames.removeAll(currentNames);
79 Set<String> deletedNames = new HashSet<String>(currentNames);
80 deletedNames.removeAll(upToDateNames);
82 for (String name : deletedNames) {
83 scheduleDeletion(file.findChild(name));
86 for (String name : newNames) {
87 boolean isDirectory = delegate.isDirectory(new FakeVirtualFile(file, name));
88 scheduleCreation(file, name, isDirectory);
91 for (VirtualFile child : file.getChildren()) {
92 if (!deletedNames.contains(child.getName())) {
93 int childAttributes = delegate.getBooleanAttributes(child, -1);
94 scheduleChildRefresh(file, child, delegate, childAttributes);
99 for (VirtualFile child : file.getCachedChildren()) {
100 int childAttributes = delegate.getBooleanAttributes(child, -1);
101 if ((childAttributes & NewVirtualFileSystem.BA_EXISTS) != 0) {
102 scheduleChildRefresh(file, child, delegate, childAttributes);
105 scheduleDeletion(child);
109 final List<String> names = dir.getSuspiciousNames();
110 for (String name : names) {
111 if (name.isEmpty()) continue;
113 final VirtualFile fake = new FakeVirtualFile(file, name);
114 int attrs = delegate.getBooleanAttributes(fake, NewVirtualFileSystem.BA_EXISTS | NewVirtualFileSystem.BA_DIRECTORY);
115 if ((attrs & NewVirtualFileSystem.BA_EXISTS) != 0) {
116 boolean isDira = (attrs & NewVirtualFileSystem.BA_DIRECTORY) != 0;
117 scheduleCreation(file, name, isDira);
123 long currentTimestamp = persistence.getTimeStamp(file);
124 long upToDateTimestamp = delegate.getTimeStamp(file);
126 if (currentTimestamp != upToDateTimestamp) {
127 scheduleUpdateContent(file);
131 boolean currentWritable = persistence.isWritable(file);
132 boolean upToDateWritable = delegate.isWritable(file);
134 if (currentWritable != upToDateWritable) {
135 scheduleWritableAttributeChange(file, currentWritable, upToDateWritable);
143 private void scheduleChildRefresh(@NotNull VirtualFileSystemEntry file,
144 @NotNull VirtualFile child,
145 @NotNull NewVirtualFileSystem delegate,
146 @NewVirtualFileSystem.FileBooleanAttributes int childAttributes) {
147 final boolean currentIsDirectory = child.isDirectory();
148 final boolean currentIsSymlink = child.isSymLink();
149 final boolean currentIsSpecial = child.isSpecialFile();
150 final boolean upToDateIsDirectory = (childAttributes & NewVirtualFileSystem.BA_DIRECTORY) != 0;
151 final boolean upToDateIsSymlink = delegate.isSymLink(child);
152 final boolean upToDateIsSpecial = (childAttributes & (NewVirtualFileSystem.BA_REGULAR | NewVirtualFileSystem.BA_DIRECTORY | NewVirtualFileSystem.BA_EXISTS)) == NewVirtualFileSystem.BA_EXISTS;
153 if (currentIsDirectory != upToDateIsDirectory || currentIsSymlink != upToDateIsSymlink || currentIsSpecial != upToDateIsSpecial) {
154 scheduleDeletion(child);
155 scheduleReCreation(file, child.getName(), upToDateIsDirectory);
157 else if (myIsRecursive || !currentIsDirectory) {
158 myRefreshQueue.addLast(child);
162 private void scheduleWritableAttributeChange(final VirtualFileSystemEntry file,
163 final boolean currentWritable,
164 final boolean upToDateWritable) {
165 myEvents.add(new VFilePropertyChangeEvent(null, file, VirtualFile.PROP_WRITABLE, currentWritable, upToDateWritable, true));
168 private void scheduleUpdateContent(final VirtualFileSystemEntry file) {
169 myEvents.add(new VFileContentChangeEvent(null, file, file.getModificationStamp(), -1, true));
172 private void scheduleCreation(final VirtualFileSystemEntry parent, final String childName, final boolean isDirectory) {
173 myEvents.add(new VFileCreateEvent(null, parent, childName, isDirectory, true, false));
176 private void scheduleReCreation(final VirtualFileSystemEntry parent, final String childName, final boolean isDirectory) {
177 myEvents.add(new VFileCreateEvent(null, parent, childName, isDirectory, true, true));
180 private void scheduleDeletion(final VirtualFile file) {
181 if (file == null) return;
182 myEvents.add(new VFileDeleteEvent(null, file, true));
185 public List<VFileEvent> getEvents() {