Win32 filesystem
[fedora-idea.git] / platform / platform-impl / src / com / intellij / openapi / vfs / newvfs / persistent / RefreshWorker.java
blobd8be748b20af57fda732c0099bca529304fdfb0f
1 /*
2 * Copyright 2000-2009 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.
18 * @author max
20 package com.intellij.openapi.vfs.newvfs.persistent;
22 import com.intellij.openapi.application.ex.ApplicationEx;
23 import com.intellij.openapi.application.ex.ApplicationManagerEx;
24 import com.intellij.openapi.util.SystemInfo;
25 import com.intellij.openapi.vfs.LocalFileSystem;
26 import com.intellij.openapi.vfs.VfsUtil;
27 import com.intellij.openapi.vfs.VirtualFile;
28 import com.intellij.openapi.vfs.impl.win32.Win32LocalFileSystem;
29 import com.intellij.openapi.vfs.newvfs.ManagingFS;
30 import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
31 import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem;
32 import com.intellij.openapi.vfs.newvfs.events.*;
33 import com.intellij.openapi.vfs.newvfs.impl.FakeVirtualFile;
34 import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl;
35 import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
36 import com.intellij.util.containers.Queue;
38 import java.util.*;
40 public class RefreshWorker {
41 private final VirtualFile myRefreshRoot;
42 private final boolean myIsRecursive;
43 private final Queue<VirtualFile> myRefreshQueue = new Queue<VirtualFile>(100);
45 private final List<VFileEvent> myEvents = new ArrayList<VFileEvent>();
47 public RefreshWorker(final VirtualFile refreshRoot, final boolean isRecursive) {
48 myRefreshRoot = refreshRoot;
49 myIsRecursive = isRecursive;
50 myRefreshQueue.addLast(refreshRoot);
53 public void scan() {
54 final NewVirtualFile root = (NewVirtualFile)myRefreshRoot;
55 NewVirtualFileSystem delegate = root.getFileSystem();
56 if (root.isDirty() && !delegate.exists(root)) {
57 scheduleDeletion(root);
58 root.markClean();
60 else {
61 ApplicationEx applicationEx = ApplicationManagerEx.getApplicationEx();
62 if (delegate.getProtocol().equals(LocalFileSystem.PROTOCOL) && SystemInfo.isWindows && root.isDirectory() &&
63 (applicationEx.isUnitTestMode() || applicationEx.isInternal())) {
64 delegate = new Win32LocalFileSystem();
66 final PersistentFS persistence = (PersistentFS)ManagingFS.getInstance();
68 while (!myRefreshQueue.isEmpty()) {
69 final VirtualFileSystemEntry file = (VirtualFileSystemEntry)myRefreshQueue.pullFirst();
70 if (!file.isDirty()) continue;
72 if (file.isDirectory()) {
73 VirtualDirectoryImpl dir = (VirtualDirectoryImpl)file;
74 final boolean fullSync = dir.allChildrenLoaded();
75 if (fullSync) {
76 Set<String> currentNames = new HashSet<String>(Arrays.asList(persistence.list(file)));
77 Set<String> uptodateNames = new HashSet<String>(Arrays.asList(VfsUtil.filterNames(delegate.list(file))));
79 Set<String> newNames = new HashSet<String>(uptodateNames);
80 newNames.removeAll(currentNames);
82 Set<String> deletedNames = new HashSet<String>(currentNames);
83 deletedNames.removeAll(uptodateNames);
85 for (String name : deletedNames) {
86 scheduleDeletion(file.findChild(name));
89 for (String name : newNames) {
90 boolean isDirectory = delegate.isDirectory(new FakeVirtualFile(file, name));
91 scheduleCreation(file, name, isDirectory);
94 for (VirtualFile child : file.getChildren()) {
95 if (!deletedNames.contains(child.getName())) {
96 scheduleChildRefresh(file, child, delegate);
100 else {
101 for (VirtualFile child : file.getCachedChildren()) {
102 if (delegate.exists(child)) {
103 scheduleChildRefresh(file, child, delegate);
105 else {
106 scheduleDeletion(child);
110 final List<String> names = dir.getSuspicousNames();
111 for (String name : names) {
112 if (name.length() == 0) continue;
114 final VirtualFile fake = new FakeVirtualFile(file, name);
115 if (delegate.exists(fake)) {
116 scheduleCreation(file, name, delegate.isDirectory(fake));
121 else {
122 long currentTimestamp = persistence.getTimeStamp(file);
123 long updtodateTimestamp = delegate.getTimeStamp(file);
125 if (currentTimestamp != updtodateTimestamp) {
126 scheduleUpdateContent(file);
130 boolean currentWritable = persistence.isWritable(file);
131 boolean uptodateWritable = delegate.isWritable(file);
133 if (currentWritable != uptodateWritable) {
134 scheduleWritableAttributeChange(file, currentWritable, uptodateWritable);
137 file.markClean();
142 private void scheduleChildRefresh(final VirtualFileSystemEntry file, final VirtualFile child, final NewVirtualFileSystem delegate) {
143 final boolean currentIsDirectory = child.isDirectory();
144 final boolean uptodateisDirectory = delegate.isDirectory(child);
145 if (currentIsDirectory != uptodateisDirectory) {
146 scheduleDeletion(child);
147 scheduleCreation(file, child.getName(), uptodateisDirectory);
149 else if (myIsRecursive || !currentIsDirectory) {
150 myRefreshQueue.addLast(child);
154 private void scheduleWritableAttributeChange(final VirtualFileSystemEntry file,
155 final boolean currentWritable,
156 final boolean uptodateWritable) {
157 myEvents.add(new VFilePropertyChangeEvent(null, file, VirtualFile.PROP_WRITABLE, currentWritable, uptodateWritable, true));
160 private void scheduleUpdateContent(final VirtualFileSystemEntry file) {
161 myEvents.add(new VFileContentChangeEvent(null, file, file.getModificationStamp(), -1, true));
164 private void scheduleCreation(final VirtualFileSystemEntry parent, final String childName, final boolean isDirectory) {
165 myEvents.add(new VFileCreateEvent(null, parent, childName, isDirectory, true));
168 private void scheduleDeletion(final VirtualFile file) {
169 if (file == null) return;
170 myEvents.add(new VFileDeleteEvent(null, file, true));
173 public List<VFileEvent> getEvents() {
174 return myEvents;