--- a/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/FileObjectCrawler.java +++ a/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/FileObjectCrawler.java @@ -43,6 +43,7 @@ import java.util.Collection; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.TreeMap; @@ -88,9 +89,15 @@ final Stats stats = LOG.isLoggable(Level.FINE) ? new Stats() : null; if (files != null) { - finished = collect(files, root, resources, allResources, stats, entry); + finished = collect(files, root, resources, allResources, stats, entry, null); } else { - finished = collect(root.getChildren(), root, resources, allResources, stats, entry); + Set seenFoldersOrFilesOrEmpty = !FileObjectKeeper.getDefault().isKnown(root) ? new HashSet() : null; + + finished = collect(root.getChildren(), root, resources, allResources, stats, entry, seenFoldersOrFilesOrEmpty); + + if (seenFoldersOrFilesOrEmpty != null && !isCancelled()) { + FileObjectKeeper.getDefault().record(root, seenFoldersOrFilesOrEmpty); + } } final long tm2 = System.currentTimeMillis(); @@ -123,7 +130,8 @@ private boolean collect (FileObject[] fos, FileObject root, final Collection resources, final Collection allResources, - final Stats stats, final ClassPath.Entry entry) { + final Stats stats, final ClassPath.Entry entry, + Set seenFoldersOrFilesOrNull) { for (FileObject fo : fos) { //keep the same logic like in RepositoryUpdater if (isCancelled()) { @@ -136,10 +144,16 @@ continue; } if (fo.isFolder()) { - if (!collect(fo.getChildren(), root, resources, allResources, stats, entry)) { + if (seenFoldersOrFilesOrNull != null && FileObjectKeeper.KEEP_FOLDERS) { + seenFoldersOrFilesOrNull.add(fo); + } + if (!collect(fo.getChildren(), root, resources, allResources, stats, entry, seenFoldersOrFilesOrNull)) { return false; } } else { + if (seenFoldersOrFilesOrNull != null && FileObjectKeeper.KEEP_FILES) { + seenFoldersOrFilesOrNull.add(fo); + } if (stats != null) { stats.filesCount++; Stats.inc(stats.extensions, fo.getExt()); --- a/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/FileObjectKeeper.java +++ a/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/FileObjectKeeper.java @@ -0,0 +1,107 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.parsing.impl.indexing; + +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileStateInvalidException; +import org.openide.util.Exceptions; + +/** + * + * @author lahvac + */ +public class FileObjectKeeper { + + private static final FileObjectKeeper INSTANCE = new FileObjectKeeper(); + + public static FileObjectKeeper getDefault() { + return INSTANCE; + } + + private static final String KEEP_KIND = System.getProperty(FileObjectKeeper.class.getName() + ".kind"); + public static final boolean KEEP_FOLDERS = "folders".equals(KEEP_KIND) || "all".equals(KEEP_KIND); + public static final boolean KEEP_FILES = "all".equals(KEEP_KIND); + + private final Map> kept = new HashMap>(); + + public synchronized boolean isKnown(FileObject root) { + try { + return kept.containsKey(root.getURL()); + } catch (FileStateInvalidException ex) { + Exceptions.printStackTrace(ex); + return false; + } + } + + public synchronized void record(FileObject root, Set files) { + try { + kept.put(root.getURL(), files); + } catch (FileStateInvalidException ex) { + Exceptions.printStackTrace(ex); + } + } + + public synchronized void remove(Iterable roots) { + for (URL u : roots) { + kept.remove(u); + } + } + + public synchronized void fileCreated(URL root, FileObject file) { + Set d = kept.get(root); + + if (d != null) { + d.add(file); + } + } + + public synchronized void fileDeleted(URL root, FileObject file) { + Set d = kept.get(root); + + if (d != null) { + d.remove(file); + } + } + +} --- a/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdater.java +++ a/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdater.java @@ -388,10 +388,14 @@ } public void fileDataCreated(FileEvent fe) { - fileChanged(fe); + fileChanged(fe, true); } public void fileChanged(FileEvent fe) { + fileChanged(fe, false); + } + + private void fileChanged(FileEvent fe, boolean newFile) { if (!authorize(fe)) { return; } @@ -403,6 +407,8 @@ if (fo != null && fo.isValid() && !isCacheFile(fo) && VisibilityQuery.getDefault().isVisible(fo)) { root = getOwningSourceRoot (fo); if (root != null) { + if (newFile) + FileObjectKeeper.getDefault().fileDeleted(root, fo);//TODO: correct place? boolean sourceForBinaryRoot = sourcesForBinaryRoots.contains(root); ClassPath.Entry entry = sourceForBinaryRoot ? null : getClassPathEntry(URLMapper.findFileObject(root)); if (entry == null || entry.includes(fo)) { @@ -436,6 +442,7 @@ if (fo != null && !isCacheFile(fo) && VisibilityQuery.getDefault().isVisible(fo)) { root = getOwningSourceRoot (fo); if (root != null) { + FileObjectKeeper.getDefault().fileDeleted(root, fo);//TODO: correct place? if (fo.isData() /*&& FileUtil.getMIMEType(fo, recognizers.getMimeTypes())!=null*/) { String relativePath = FileUtil.getRelativePath(URLMapper.findFileObject(root), fo); assert relativePath != null : "FileObject not under root: f=" + fo + ", root=" + root; //NOI18N @@ -2431,6 +2438,7 @@ for (IndexerCache.IndexerInfo embeddingIndexer : embeddingIndexers) { embeddingIndexer.getIndexerFactory().rootsRemoved(roots); } + FileObjectKeeper.getDefault().remove(roots); } }