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.
20 package com
.intellij
.openapi
.vfs
.newvfs
.persistent
;
22 import com
.intellij
.openapi
.util
.SystemInfo
;
23 import com
.intellij
.openapi
.util
.registry
.Registry
;
24 import com
.intellij
.openapi
.vfs
.LocalFileSystem
;
25 import com
.intellij
.openapi
.vfs
.VfsUtil
;
26 import com
.intellij
.openapi
.vfs
.VirtualFile
;
27 import com
.intellij
.openapi
.vfs
.impl
.win32
.Win32LocalFileSystem
;
28 import com
.intellij
.openapi
.vfs
.newvfs
.ManagingFS
;
29 import com
.intellij
.openapi
.vfs
.newvfs
.NewVirtualFile
;
30 import com
.intellij
.openapi
.vfs
.newvfs
.NewVirtualFileSystem
;
31 import com
.intellij
.openapi
.vfs
.newvfs
.events
.*;
32 import com
.intellij
.openapi
.vfs
.newvfs
.impl
.FakeVirtualFile
;
33 import com
.intellij
.openapi
.vfs
.newvfs
.impl
.VirtualDirectoryImpl
;
34 import com
.intellij
.openapi
.vfs
.newvfs
.impl
.VirtualFileSystemEntry
;
35 import com
.intellij
.util
.containers
.Queue
;
39 public class RefreshWorker
{
40 private final VirtualFile myRefreshRoot
;
41 private final boolean myIsRecursive
;
42 private final Queue
<VirtualFile
> myRefreshQueue
= new Queue
<VirtualFile
>(100);
44 private final List
<VFileEvent
> myEvents
= new ArrayList
<VFileEvent
>();
46 public RefreshWorker(final VirtualFile refreshRoot
, final boolean isRecursive
) {
47 myRefreshRoot
= refreshRoot
;
48 myIsRecursive
= isRecursive
;
49 myRefreshQueue
.addLast(refreshRoot
);
53 final NewVirtualFile root
= (NewVirtualFile
)myRefreshRoot
;
54 NewVirtualFileSystem delegate
= root
.getFileSystem();
55 if (root
.isDirty() && !delegate
.exists(root
)) {
56 scheduleDeletion(root
);
60 if (delegate
.getProtocol().equals(LocalFileSystem
.PROTOCOL
) &&
62 Registry
.is("filesystem.useNative")) {
64 if (SystemInfo
.isWindows
&& Win32LocalFileSystem
.isAvailable()) {
65 delegate
= Win32LocalFileSystem
.getWin32Instance();
69 final PersistentFS persistence
= (PersistentFS
)ManagingFS
.getInstance();
71 while (!myRefreshQueue
.isEmpty()) {
72 final VirtualFileSystemEntry file
= (VirtualFileSystemEntry
)myRefreshQueue
.pullFirst();
73 if (!file
.isDirty()) continue;
75 if (file
.isDirectory()) {
76 VirtualDirectoryImpl dir
= (VirtualDirectoryImpl
)file
;
77 final boolean fullSync
= dir
.allChildrenLoaded();
79 Set
<String
> currentNames
= new HashSet
<String
>(Arrays
.asList(persistence
.list(file
)));
80 Set
<String
> uptodateNames
= new HashSet
<String
>(Arrays
.asList(VfsUtil
.filterNames(delegate
.list(file
))));
82 Set
<String
> newNames
= new HashSet
<String
>(uptodateNames
);
83 newNames
.removeAll(currentNames
);
85 Set
<String
> deletedNames
= new HashSet
<String
>(currentNames
);
86 deletedNames
.removeAll(uptodateNames
);
88 for (String name
: deletedNames
) {
89 scheduleDeletion(file
.findChild(name
));
92 for (String name
: newNames
) {
93 boolean isDirectory
= delegate
.isDirectory(new FakeVirtualFile(file
, name
));
94 scheduleCreation(file
, name
, isDirectory
);
97 for (VirtualFile child
: file
.getChildren()) {
98 if (!deletedNames
.contains(child
.getName())) {
99 scheduleChildRefresh(file
, child
, delegate
);
104 for (VirtualFile child
: file
.getCachedChildren()) {
105 if (delegate
.exists(child
)) {
106 scheduleChildRefresh(file
, child
, delegate
);
109 scheduleDeletion(child
);
113 final List
<String
> names
= dir
.getSuspicousNames();
114 for (String name
: names
) {
115 if (name
.length() == 0) continue;
117 final VirtualFile fake
= new FakeVirtualFile(file
, name
);
118 if (delegate
.exists(fake
)) {
119 scheduleCreation(file
, name
, delegate
.isDirectory(fake
));
125 long currentTimestamp
= persistence
.getTimeStamp(file
);
126 long updtodateTimestamp
= delegate
.getTimeStamp(file
);
128 if (currentTimestamp
!= updtodateTimestamp
) {
129 scheduleUpdateContent(file
);
133 boolean currentWritable
= persistence
.isWritable(file
);
134 boolean uptodateWritable
= delegate
.isWritable(file
);
136 if (currentWritable
!= uptodateWritable
) {
137 scheduleWritableAttributeChange(file
, currentWritable
, uptodateWritable
);
145 private void scheduleChildRefresh(final VirtualFileSystemEntry file
, final VirtualFile child
, final NewVirtualFileSystem delegate
) {
146 final boolean currentIsDirectory
= child
.isDirectory();
147 final boolean uptodateisDirectory
= delegate
.isDirectory(child
);
148 if (currentIsDirectory
!= uptodateisDirectory
) {
149 scheduleDeletion(child
);
150 scheduleCreation(file
, child
.getName(), uptodateisDirectory
);
152 else if (myIsRecursive
|| !currentIsDirectory
) {
153 myRefreshQueue
.addLast(child
);
157 private void scheduleWritableAttributeChange(final VirtualFileSystemEntry file
,
158 final boolean currentWritable
,
159 final boolean uptodateWritable
) {
160 myEvents
.add(new VFilePropertyChangeEvent(null, file
, VirtualFile
.PROP_WRITABLE
, currentWritable
, uptodateWritable
, true));
163 private void scheduleUpdateContent(final VirtualFileSystemEntry file
) {
164 myEvents
.add(new VFileContentChangeEvent(null, file
, file
.getModificationStamp(), -1, true));
167 private void scheduleCreation(final VirtualFileSystemEntry parent
, final String childName
, final boolean isDirectory
) {
168 myEvents
.add(new VFileCreateEvent(null, parent
, childName
, isDirectory
, true));
171 private void scheduleDeletion(final VirtualFile file
) {
172 if (file
== null) return;
173 myEvents
.add(new VFileDeleteEvent(null, file
, true));
176 public List
<VFileEvent
> getEvents() {