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
.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
;
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
);
54 final NewVirtualFile root
= (NewVirtualFile
)myRefreshRoot
;
55 NewVirtualFileSystem delegate
= root
.getFileSystem();
56 if (root
.isDirty() && !delegate
.exists(root
)) {
57 scheduleDeletion(root
);
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();
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
);
101 for (VirtualFile child
: file
.getCachedChildren()) {
102 if (delegate
.exists(child
)) {
103 scheduleChildRefresh(file
, child
, delegate
);
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
));
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
);
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() {