--- a/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdater.java +++ a/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdater.java @@ -101,6 +101,7 @@ import org.netbeans.modules.parsing.api.UserTask; import org.netbeans.modules.parsing.impl.SourceAccessor; import org.netbeans.modules.parsing.impl.SourceFlags; +import org.netbeans.modules.parsing.impl.TaskProcessor; import org.netbeans.modules.parsing.impl.Utilities; import org.netbeans.modules.parsing.impl.event.EventSupport; import org.netbeans.modules.parsing.impl.indexing.IndexerCache.IndexerInfo; @@ -3863,14 +3864,14 @@ private FileChangeListener binariesListener = null; private final Map sourceRoots = new HashMap(); private final Map> binaryRoots = new HashMap>(); - + public RootsListeners() { } public void setListener(FileChangeListener sourcesListener, FileChangeListener binariesListener) { assert (sourcesListener != null && binariesListener != null) || (sourcesListener == null && binariesListener == null) : "Both sourcesListener and binariesListener must either be null or non-null"; //NOI18N - + //todo: remove removeRecursiveListener from synchronized block synchronized (this) { if (sourcesListener != null) { assert this.sourcesListener == null : "Already using " + this.sourcesListener + "and " + this.binariesListener //NOI18N @@ -3923,13 +3924,14 @@ } private void interruptibleAddRecursiveListener(URL root, boolean sourceRoot) { + Pair toAdd = null; synchronized (this) { if (sourceRoot) { if (sourcesListener != null) { if (!sourceRoots.containsKey(root) && root.getProtocol().equals("file")) { //NOI18N try { File f = new File(root.toURI()); - FileUtil.addRecursiveListener(sourcesListener, f); + toAdd = Pair.of (f,sourcesListener); sourceRoots.put(root, f); } catch (URISyntaxException use) { LOGGER.log(Level.INFO, null, use); @@ -3953,7 +3955,7 @@ FileUtil.addFileChangeListener(binariesListener, f); } else { // listening on a folder - FileUtil.addRecursiveListener(binariesListener, f); + toAdd = Pair.of(f,binariesListener); } binaryRoots.put(root, Pair.of(f, archiveUrl != null)); } @@ -3961,30 +3963,38 @@ } } } - } - - public void remove(URL root, boolean sourceRoot) { - synchronized (this) { - if (sourceRoot) { - if (sourcesListener != null) { - File f = sourceRoots.remove(root); - if (f != null) { - safeRemoveRecursiveListener(sourcesListener, f); - } - } - } else { - if (binariesListener != null) { - Pair pair = binaryRoots.remove(root); - if (pair != null) { - if (pair.second) { - FileUtil.removeFileChangeListener(binariesListener, pair.first); - } else { - safeRemoveRecursiveListener(binariesListener, pair.first); - } - } - } - } - } + if (toAdd != null) { + FileUtil.addRecursiveListener(toAdd.second, toAdd.first); + } + } + + public void remove(final URL root, final boolean sourceRoot) { + final RequestProcessor.Task task = RP.post(new Runnable() { //Serialize requests into single thread + public @Override void run() { + synchronized (this) { //Synchronized to ensure visibility + if (sourceRoot) { + if (sourcesListener != null) { + File f = sourceRoots.remove(root); + if (f != null) { + safeRemoveRecursiveListener(sourcesListener, f); + } + } + } else { + if (binariesListener != null) { + Pair pair = binaryRoots.remove(root); + if (pair != null) { + if (pair.second) { + FileUtil.removeFileChangeListener(binariesListener, pair.first); + } else { + safeRemoveRecursiveListener(binariesListener, pair.first); + } + } + } + } + } + } + }); + task.waitFinished(); } private void safeRemoveRecursiveListener(FileChangeListener listener, File path) {