diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerImpl.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerImpl.java index 4ee35f67797b..57f4b67dbcbf 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerImpl.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -284,9 +284,7 @@ public class ArtifactManagerImpl extends ArtifactManager implements ProjectCompo ContainerUtil.addIfNotNull(request, requestsToRemove); } - final LocalFileSystem fileSystem = LocalFileSystem.getInstance(); - fileSystem.removeWatchedRoots(requestsToRemove); - final Set newRequests = fileSystem.addRootsToWatch(toAdd, true); + Set newRequests = LocalFileSystem.getInstance().replaceWatchedRoots(requestsToRemove, toAdd, true); for (LocalFileSystem.WatchRequest request : newRequests) { myWatchedOutputs.put(request.getRootPath(), request); } diff --git a/java/java-impl/src/com/intellij/openapi/roots/impl/CompilerProjectExtensionImpl.java b/java/java-impl/src/com/intellij/openapi/roots/impl/CompilerProjectExtensionImpl.java index b491285c9cef..328faa3b77e1 100644 --- a/java/java-impl/src/com/intellij/openapi/roots/impl/CompilerProjectExtensionImpl.java +++ b/java/java-impl/src/com/intellij/openapi/roots/impl/CompilerProjectExtensionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -98,12 +98,7 @@ public class CompilerProjectExtensionImpl extends CompilerProjectExtension { public void setCompilerOutputUrl(String compilerOutputUrl) { VirtualFilePointer pointer = VirtualFilePointerManager.getInstance().create(compilerOutputUrl, myProject, null); setCompilerOutputPointer(pointer); - final LocalFileSystem.WatchRequest watchRequest = - LocalFileSystem.getInstance().addRootToWatch(ProjectRootManagerImpl.extractLocalPath(compilerOutputUrl), true); - if (myCompilerOutputWatchRequest != null) { - LocalFileSystem.getInstance().removeWatchedRoot(myCompilerOutputWatchRequest); - } - myCompilerOutputWatchRequest = watchRequest; + myCompilerOutputWatchRequest = LocalFileSystem.getInstance().replaceWatchedRoot(myCompilerOutputWatchRequest, compilerOutputUrl, true); } @NotNull diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java index db298eddd1f6..517d2ca07783 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java @@ -614,12 +614,7 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj private void addRootsToWatch() { final Set rootPaths = getAllRoots(false); if (rootPaths == null) return; - - final Set newRootsToWatch = LocalFileSystem.getInstance().addRootsToWatch(rootPaths, true); - - //remove old requests after adding new ones, helps avoiding unnecessary synchronizations - LocalFileSystem.getInstance().removeWatchedRoots(myRootsToWatch); - myRootsToWatch = newRootsToWatch; + myRootsToWatch = LocalFileSystem.getInstance().replaceWatchedRoots(myRootsToWatch, rootPaths, true); } @Nullable diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/JarDirectoryWatcher.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/JarDirectoryWatcher.java index 4be3f5234824..b59388e101d0 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/JarDirectoryWatcher.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/JarDirectoryWatcher.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.openapi.roots.impl.libraries; import com.intellij.openapi.Disposable; @@ -12,17 +27,15 @@ import com.intellij.openapi.vfs.newvfs.events.*; import com.intellij.util.messages.MessageBusConnection; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.List; +import java.util.*; /** * @author ksafonov */ public abstract class JarDirectoryWatcher implements Disposable { - private final JarDirectories myJarDirectories; private MessageBusConnection myBusConnection = null; - private final List myWatchRequests = new ArrayList(); + private Collection myWatchRequests = Collections.emptySet(); public JarDirectoryWatcher(JarDirectories jarDirectories) { myJarDirectories = jarDirectories; @@ -30,21 +43,39 @@ public abstract class JarDirectoryWatcher implements Disposable { public void updateWatchedRoots() { final LocalFileSystem fs = LocalFileSystem.getInstance(); - if (!myWatchRequests.isEmpty()) { - fs.removeWatchedRoots(myWatchRequests); - myWatchRequests.clear(); - } if (!myJarDirectories.isEmpty()) { + final Set recursiveRoots = new HashSet(); + final Set flatRoots = new HashSet(); final VirtualFileManager fm = VirtualFileManager.getInstance(); for (OrderRootType rootType : myJarDirectories.getRootTypes()) { for (String url : myJarDirectories.getDirectories(rootType)) { if (fm.getFileSystem(VirtualFileManager.extractProtocol(url)) instanceof LocalFileSystem) { final boolean watchRecursively = myJarDirectories.isRecursive(rootType, url); - final LocalFileSystem.WatchRequest request = fs.addRootToWatch(VirtualFileManager.extractPath(url), watchRecursively); - myWatchRequests.add(request); + final String path = VirtualFileManager.extractPath(url); + (watchRecursively ? recursiveRoots : flatRoots).add(path); } } } + + if (flatRoots.isEmpty()) { + myWatchRequests = fs.replaceWatchedRoots(myWatchRequests, recursiveRoots, true); + } + else if (recursiveRoots.isEmpty()) { + myWatchRequests = fs.replaceWatchedRoots(myWatchRequests, flatRoots, false); + } + else { + fs.removeWatchedRoots(myWatchRequests); + final int rootsTotal = flatRoots.size() + recursiveRoots.size(); + if (rootsTotal > 0) { + myWatchRequests = new ArrayList(rootsTotal); + myWatchRequests.addAll(fs.addRootsToWatch(flatRoots, false)); + myWatchRequests.addAll(fs.addRootsToWatch(recursiveRoots, true)); + } + else { + myWatchRequests = Collections.emptySet(); + } + } + if (myBusConnection == null) { myBusConnection = ApplicationManager.getApplication().getMessageBus().connect(); myBusConnection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() { @@ -58,17 +89,18 @@ public abstract class JarDirectoryWatcher implements Disposable { for (VFileEvent event : events) { if (event instanceof VFileCopyEvent) { final VFileCopyEvent copyEvent = (VFileCopyEvent)event; + final VirtualFile file = copyEvent.getFile(); if (isUnderJarDirectory(copyEvent.getNewParent() + "/" + copyEvent.getNewChildName()) || - isUnderJarDirectory(copyEvent.getFile().getUrl())) { + file != null && isUnderJarDirectory(file.getUrl())) { changesDetected = true; break; } } else if (event instanceof VFileMoveEvent) { final VFileMoveEvent moveEvent = (VFileMoveEvent)event; - final VirtualFile file = moveEvent.getFile(); - if (isUnderJarDirectory(file.getUrl()) || isUnderJarDirectory(moveEvent.getOldParent().getUrl() + "/" + file.getName())) { + if (file != null && + (isUnderJarDirectory(file.getUrl()) || isUnderJarDirectory(moveEvent.getOldParent().getUrl() + "/" + file.getName()))) { changesDetected = true; break; } @@ -106,11 +138,7 @@ public abstract class JarDirectoryWatcher implements Disposable { } } else { - final MessageBusConnection connection = myBusConnection; - if (connection != null) { - myBusConnection = null; - connection.disconnect(); - } + cleanup(); } } @@ -118,13 +146,19 @@ public abstract class JarDirectoryWatcher implements Disposable { @Override public void dispose() { + cleanup(); + } + + private void cleanup() { if (!myWatchRequests.isEmpty()) { LocalFileSystem.getInstance().removeWatchedRoots(myWatchRequests); - myWatchRequests.clear(); + myWatchRequests = Collections.emptySet(); } - if (myBusConnection != null) { - myBusConnection.disconnect(); + + final MessageBusConnection connection = myBusConnection; + if (connection != null) { myBusConnection = null; + connection.disconnect(); } } } diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/LocalFileSystem.java b/platform/platform-api/src/com/intellij/openapi/vfs/LocalFileSystem.java index 82420a7cb661..900c009995ad 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/LocalFileSystem.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/LocalFileSystem.java @@ -25,8 +25,11 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; import java.util.Collection; +import java.util.Collections; import java.util.Set; +import static java.util.Collections.singleton; + public abstract class LocalFileSystem extends NewVirtualFileSystem { @NonNls public static final String PROTOCOL = "file"; @NonNls public static final String PROTOCOL_PREFIX = PROTOCOL + "://"; @@ -125,14 +128,34 @@ public abstract class LocalFileSystem extends NewVirtualFileSystem { } @Nullable - public abstract WatchRequest addRootToWatch(@NotNull final String rootPath, final boolean toWatchRecursively); + public WatchRequest addRootToWatch(@NotNull final String rootPath, final boolean watchRecursively) { + final Set result = addRootsToWatch(singleton(rootPath), watchRecursively); + return result.size() == 1 ? result.iterator().next() : null; + } @NotNull - public abstract Set addRootsToWatch(@NotNull final Collection rootPaths, final boolean toWatchRecursively); + public abstract Set addRootsToWatch(@NotNull final Collection rootPaths, final boolean watchRecursively); - public abstract void removeWatchedRoots(@NotNull final Collection rootsToWatch); + public void removeWatchedRoot(@Nullable final WatchRequest watchRequest) { + if (watchRequest != null) { + removeWatchedRoots(singleton(watchRequest)); + } + } - public abstract void removeWatchedRoot(@NotNull final WatchRequest watchRequest); + public abstract void removeWatchedRoots(@NotNull final Collection watchRequests); + + @Nullable + public WatchRequest replaceWatchedRoot(@Nullable final WatchRequest watchRequest, + @NotNull final String rootPath, + final boolean watchRecursively) { + final Set requests = watchRequest != null ? singleton(watchRequest) : Collections.emptySet(); + final Set result = replaceWatchedRoots(requests, singleton(rootPath), watchRecursively); + return result.size() == 1 ? result.iterator().next() : null; + } + + public abstract Set replaceWatchedRoots(@NotNull final Collection watchRequests, + @NotNull final Collection rootPaths, + final boolean watchRecursively); public abstract void registerAuxiliaryFileOperationsHandler(@NotNull LocalFileOperationsHandler handler); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java index 2e528457a167..40b0f50325ab 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java @@ -15,12 +15,11 @@ */ package com.intellij.openapi.vfs.impl.local; +import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.io.FileAttributes; import com.intellij.openapi.util.io.FileSystemUtil; import com.intellij.openapi.util.io.FileUtil; @@ -114,6 +113,12 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap public void disposeComponent() { } + @Override + @NotNull + public String getComponentName() { + return "LocalFileSystem"; + } + @TestOnly public void cleanupForNextTest(Set survivors) throws IOException { ApplicationManager.getApplication().runWriteAction(new Runnable() { @@ -231,31 +236,29 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap private void setUpFileWatcher() { final Application application = ApplicationManager.getApplication(); + if (application.isDisposeInProgress() || !myWatcher.isOperational()) return; - if (application.isDisposeInProgress()) return; + final AccessToken token = application.acquireReadActionLock(); + try { + synchronized (myLock) { + final WatchRequestImpl[] watchRequests = normalizeRootsForRefresh(); + final List myRecursiveRoots = new ArrayList(); + final List myFlatRoots = new ArrayList(); - if (myWatcher.isOperational()) { - application.runReadAction(new Runnable() { - @Override - public void run() { - synchronized (myLock) { - final WatchRequestImpl[] watchRequests = normalizeRootsForRefresh(); - List myRecursiveRoots = new ArrayList(); - List myFlatRoots = new ArrayList(); - - for (WatchRequestImpl root : watchRequests) { - if (root.isToWatchRecursively()) { - myRecursiveRoots.add(root.myFSRootPath); - } - else { - myFlatRoots.add(root.myFSRootPath); - } - } - - myWatcher.setWatchRoots(myRecursiveRoots, myFlatRoots); + for (WatchRequestImpl watchRequest : watchRequests) { + if (watchRequest.isToWatchRecursively()) { + myRecursiveRoots.add(watchRequest.myFSRootPath); + } + else { + myFlatRoots.add(watchRequest.myFSRootPath); } } - }); + + myWatcher.setWatchRoots(myRecursiveRoots, myFlatRoots); + } + } + finally { + token.finish(); } } @@ -280,48 +283,6 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap } } - @Override - @NotNull - public String getComponentName() { - return "LocalFileSystem"; - } - - @Override - public WatchRequest addRootToWatch(@NotNull final String rootPath, final boolean toWatchRecursively) { - if (rootPath.length() == 0 || !myWatcher.isOperational()) return null; - - Application app = ApplicationManager.getApplication(); - return app.runReadAction(new Computable() { - @Override - public WatchRequest compute() { - synchronized (myLock) { - final WatchRequestImpl result = new WatchRequestImpl(rootPath, toWatchRecursively); - boolean alreadyWatched = isAlreadyWatched(result); - if (!alreadyWatched) { - final VirtualFile existingFile = findFileByPathIfCached(rootPath); - if (existingFile != null) { - final ModalityState modalityState = ModalityState.defaultModalityState(); - RefreshQueue.getInstance().refresh(true, toWatchRecursively, null, modalityState, existingFile); - if (existingFile.isDirectory() && !toWatchRecursively && existingFile instanceof NewVirtualFile) { - for (VirtualFile child : ((NewVirtualFile)existingFile).getCachedChildren()) { - RefreshQueue.getInstance().refresh(true, false, null, modalityState, child); - } - } - } - } - myRootsToWatch.add(result); - if (alreadyWatched) { - result.myDominated = true; - return result; - } - myCachedNormalizedRequests = null; - setUpFileWatcher(); - return result; - } - } - }); - } - private boolean isAlreadyWatched(final WatchRequestImpl request) { for (final WatchRequestImpl current : normalizeRootsForRefresh()) { if (dominates(current, request)) return true; @@ -339,74 +300,114 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap @Override @NotNull - public Set addRootsToWatch(@NotNull final Collection rootPaths, final boolean toWatchRecursively) { - if (!myWatcher.isOperational()) return Collections.emptySet(); + public Set addRootsToWatch(@NotNull final Collection rootPaths, final boolean watchRecursively) { + if (rootPaths.isEmpty() || !myWatcher.isOperational()) { + return Collections.emptySet(); + } + else { + return replaceWatchedRoots(Collections.emptySet(), rootPaths, watchRecursively); + } + } - final Set result = new HashSet(); - final Set filesToSynchronize = new HashSet(); + @Override + public void removeWatchedRoots(@NotNull final Collection watchRequests) { + if (watchRequests.isEmpty()) return; - Application application = ApplicationManager.getApplication(); - application.runReadAction(new Runnable() { - public void run() { - synchronized (myLock) { - for (String rootPath : rootPaths) { - LOG.assertTrue(rootPath != null); - if (rootPath.length() > 0) { - final WatchRequestImpl request = new WatchRequestImpl(rootPath, toWatchRecursively); - final VirtualFile existingFile = findFileByPathIfCached(rootPath); - if (existingFile != null) { - if (!isAlreadyWatched(request)) { - filesToSynchronize.add(existingFile); - } - } - result.add(request); - myRootsToWatch.add(request); //add in any case, safe to add inplace without copying myRootsToWatch before the loop - } - } + final AccessToken token = ApplicationManager.getApplication().acquireReadActionLock(); + try { + synchronized (myLock) { + final boolean update = doRemoveWatchedRoots(watchRequests); + if (update) { myCachedNormalizedRequests = null; setUpFileWatcher(); } } - }); + } + finally { + token.finish(); + } + } - if (!application.isUnitTestMode() && !filesToSynchronize.isEmpty()) { - for (VirtualFile file : filesToSynchronize) { - if (file instanceof NewVirtualFile && file.getFileSystem() instanceof LocalFileSystem) { - ((NewVirtualFile)file).markDirtyRecursively(); + @Override + public Set replaceWatchedRoots(@NotNull final Collection watchRequests, + @NotNull final Collection rootPaths, + final boolean watchRecursively) { + if (rootPaths.isEmpty() || !myWatcher.isOperational()) { + removeWatchedRoots(watchRequests); + return Collections.emptySet(); + } + + final Set result = new HashSet(); + final Set filesToSync = new HashSet(); + + final AccessToken token = ApplicationManager.getApplication().acquireReadActionLock(); + try { + synchronized (myLock) { + final boolean update = doAddRootsToWatch(rootPaths, watchRecursively, result, filesToSync) || + doRemoveWatchedRoots(watchRequests); + if (update) { + myCachedNormalizedRequests = null; + setUpFileWatcher(); } } - refreshFiles(filesToSynchronize, true, toWatchRecursively, null); } + finally { + token.finish(); + } + + syncFiles(filesToSync, watchRecursively); return result; } - @Override - public void removeWatchedRoot(@NotNull final WatchRequest watchRequest) { - ApplicationManager.getApplication().runReadAction(new Runnable() { - public void run() { - synchronized (myLock) { - if (myRootsToWatch.remove((WatchRequestImpl)watchRequest) && !((WatchRequestImpl)watchRequest).myDominated) { - myCachedNormalizedRequests = null; - setUpFileWatcher(); + private boolean doAddRootsToWatch(@NotNull final Collection roots, + final boolean recursively, + @NotNull final Set results, + @NotNull final Set filesToSync) { + boolean update = false; + + for (String root : roots) { + final WatchRequestImpl result = new WatchRequestImpl(root, recursively); + final boolean alreadyWatched = isAlreadyWatched(result); + + if (!alreadyWatched) { + final VirtualFile existingFile = findFileByPathIfCached(root); + if (existingFile != null) { + if (existingFile.isDirectory() && !recursively && existingFile instanceof NewVirtualFile) { + filesToSync.addAll(((NewVirtualFile)existingFile).getCachedChildren()); } } } - }); + result.myDominated = alreadyWatched; + myRootsToWatch.add(result); + results.add(result); + + update |= !alreadyWatched; + } + + return update; } - @Override - public void removeWatchedRoots(@NotNull final Collection rootsToWatch) { - ApplicationManager.getApplication().runReadAction(new Runnable() { - public void run() { - synchronized (myLock) { - if (myRootsToWatch.removeAll(rootsToWatch)) { - myCachedNormalizedRequests = null; - setUpFileWatcher(); - } - } + private void syncFiles(@NotNull final Set filesToSync, final boolean watchRecursively) { + if (filesToSync.isEmpty() || ApplicationManager.getApplication().isUnitTestMode()) return; + + for (VirtualFile file : filesToSync) { + if (file instanceof NewVirtualFile && file.getFileSystem() instanceof LocalFileSystem) { + ((NewVirtualFile)file).markDirtyRecursively(); } - }); + } + refreshFiles(filesToSync, true, watchRecursively, null); + } + + private boolean doRemoveWatchedRoots(@NotNull final Collection watchRequests) { + boolean update = false; + + for (WatchRequest watchRequest : watchRequests) { + final boolean wasWatched = myRootsToWatch.remove((WatchRequestImpl)watchRequest) && !((WatchRequestImpl)watchRequest).myDominated; + update |= wasWatched; + } + + return update; } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java index 621f7612e4ef..0bba1c9e3913 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java @@ -181,24 +181,19 @@ public class Win32LocalFileSystem extends LocalFileSystemBase { } } - @Override - public WatchRequest addRootToWatch(@NotNull String rootPath, boolean toWatchRecursively) { - throw new UnsupportedOperationException(); - } - @NotNull @Override - public Set addRootsToWatch(@NotNull Collection rootPaths, boolean toWatchRecursively) { + public Set addRootsToWatch(@NotNull Collection rootPaths, boolean watchRecursively) { throw new UnsupportedOperationException(); } @Override - public void removeWatchedRoots(@NotNull Collection rootsToWatch) { + public void removeWatchedRoots(@NotNull Collection watchRequests) { throw new UnsupportedOperationException(); } @Override - public void removeWatchedRoot(@NotNull WatchRequest watchRequest) { + public Set replaceWatchedRoots(@NotNull Collection watchRequests, @NotNull Collection rootPaths, boolean watchRecursively) { throw new UnsupportedOperationException(); } diff --git a/platform/testFramework/src/com/intellij/mock/MockLocalFileSystem.java b/platform/testFramework/src/com/intellij/mock/MockLocalFileSystem.java index 8c96630f68b2..ed6438d539cc 100644 --- a/platform/testFramework/src/com/intellij/mock/MockLocalFileSystem.java +++ b/platform/testFramework/src/com/intellij/mock/MockLocalFileSystem.java @@ -81,24 +81,20 @@ public class MockLocalFileSystem extends LocalFileSystem { public void refreshFiles(@NotNull Iterable files, boolean async, boolean recursive, @Nullable Runnable onFinish) { } - @Override - @Nullable - public WatchRequest addRootToWatch(@NotNull final String rootPath, final boolean toWatchRecursively) { - throw new UnsupportedOperationException("'addRootToWatch' not implemented in " + getClass().getName()); - } - @Override @NotNull - public Set addRootsToWatch(@NotNull final Collection rootPaths, final boolean toWatchRecursively) { - throw new UnsupportedOperationException("'addRootsToWatch' not implemented in " + getClass().getName()); + public Set addRootsToWatch(@NotNull final Collection rootPaths, final boolean watchRecursively) { + throw new UnsupportedOperationException("Not implemented in " + getClass().getName()); } @Override public void removeWatchedRoots(@NotNull final Collection rootsToWatch) { + throw new UnsupportedOperationException("Not implemented in " + getClass().getName()); } @Override - public void removeWatchedRoot(@NotNull final WatchRequest watchRequest) { + public Set replaceWatchedRoots(@NotNull Collection watchRequests, @NotNull Collection rootPaths, boolean watchRecursively) { + throw new UnsupportedOperationException("Not implemented in " + getClass().getName()); } @Override diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/FileWatchRequestModifier.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/FileWatchRequestModifier.java index 00c37e150e8c..b2fb77cc96aa 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/FileWatchRequestModifier.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/FileWatchRequestModifier.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,10 +19,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.VcsDirectoryMapping; import com.intellij.openapi.vfs.LocalFileSystem; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author irengrig @@ -51,17 +48,25 @@ public class FileWatchRequestModifier implements Runnable { final List deleted = new LinkedList(myDirectoryMappingWatches.keySet()); deleted.removeAll(copy); + final Map toAdd = new HashMap(); for (VcsDirectoryMapping mapping : added) { - if (mapping.isDefaultMapping()) continue; - final LocalFileSystem.WatchRequest watchRequest = myLfs.addRootToWatch(mapping.getDirectory(), true); - myDirectoryMappingWatches.put(mapping, watchRequest); + if (!mapping.isDefaultMapping()) { + toAdd.put(mapping.getDirectory(), mapping); + } } + + final Collection toRemove = new ArrayList(); for (VcsDirectoryMapping mapping : deleted) { if (mapping.isDefaultMapping()) continue; final LocalFileSystem.WatchRequest removed = myDirectoryMappingWatches.remove(mapping); if (removed != null) { - myLfs.removeWatchedRoot(removed); + toRemove.add(removed); } } + + final Set requests = myLfs.replaceWatchedRoots(toRemove, toAdd.keySet(), true); + for (LocalFileSystem.WatchRequest request : requests) { + myDirectoryMappingWatches.put(toAdd.get(request.getRootPath()), request); + } } } diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/FetchExtResourceAction.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/FetchExtResourceAction.java index 78e3e6f4a4ff..ff395f1acd04 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/FetchExtResourceAction.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/FetchExtResourceAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.javaee.ExternalResourceManager; +import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; @@ -31,6 +32,7 @@ import com.intellij.openapi.roots.WatchedRootsProvider; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; @@ -166,26 +168,23 @@ public class FetchExtResourceAction extends BaseExtResourceAction implements Wat }); } - private void fetchDtd(final Project project, final String dtdUrl, final String url, final ProgressIndicator indicator) - throws IOException { - + private void fetchDtd(final Project project, final String dtdUrl, final String url, final ProgressIndicator indicator) throws IOException { final String extResourcesPath = getExternalResourcesPath(); final File extResources = new File(extResourcesPath); - final boolean alreadyExists = extResources.exists(); - extResources.mkdirs(); - LOG.assertTrue(extResources.exists()); + LOG.assertTrue(extResources.mkdirs() || extResources.exists(), extResources); final PsiManager psiManager = PsiManager.getInstance(project); ApplicationManager.getApplication().invokeAndWait(new Runnable() { public void run() { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByPath( - extResources.getAbsolutePath().replace(File.separatorChar, '/')); - LOG.assertTrue(vFile != null); - if (!alreadyExists) LocalFileSystem.getInstance().addRootToWatch(vFile.getPath(), true); - } - }); + final AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(FetchExtResourceAction.class); + try { + final String path = FileUtil.toSystemIndependentName(extResources.getAbsolutePath()); + final VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(path); + LOG.assertTrue(vFile != null, path); + } + finally { + token.finish(); + } } }, indicator.getModalityState());