diff --git a/java.source/nbproject/project.properties b/java.source/nbproject/project.properties --- a/java.source/nbproject/project.properties +++ b/java.source/nbproject/project.properties @@ -46,7 +46,7 @@ javadoc.title=Java Source javadoc.arch=${basedir}/arch.xml javadoc.apichanges=${basedir}/apichanges.xml -spec.version.base=0.113 +spec.version.base=0.114 test.qa-functional.cp.extra=${refactoring.java.dir}/modules/ext/nb-javac-api.jar test.unit.run.cp.extra=${o.n.core.dir}/core/core.jar:\ ${o.n.core.dir}/lib/boot.jar:\ diff --git a/java.source/src/org/netbeans/api/java/source/SourceUtils.java b/java.source/src/org/netbeans/api/java/source/SourceUtils.java --- a/java.source/src/org/netbeans/api/java/source/SourceUtils.java +++ b/java.source/src/org/netbeans/api/java/source/SourceUtils.java @@ -91,12 +91,10 @@ import org.netbeans.api.editor.mimelookup.MimePath; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.lexer.JavaTokenId; -import org.netbeans.api.java.classpath.GlobalPathRegistry; import org.netbeans.api.java.queries.JavadocForBinaryQuery; import org.netbeans.api.java.queries.SourceForBinaryQuery; import org.netbeans.api.java.source.ClasspathInfo.PathKind; import org.netbeans.api.java.source.JavaSource.Phase; -import static org.netbeans.api.java.source.SourceUtils.getDependentRootsImpl; import org.netbeans.api.java.source.matching.Matcher; import org.netbeans.api.java.source.matching.Occurrence; import org.netbeans.api.java.source.matching.Pattern; @@ -120,7 +118,7 @@ import org.netbeans.modules.parsing.api.ResultIterator; import org.netbeans.modules.parsing.api.UserTask; import org.netbeans.modules.parsing.api.indexing.IndexingManager; -import org.netbeans.modules.parsing.impl.indexing.friendapi.IndexingController; +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport; import org.netbeans.spi.java.classpath.support.ClassPathSupport; import org.openide.filesystems.FileObject; @@ -672,11 +670,10 @@ * incoming root, never returns null. * @since 0.10 */ - @org.netbeans.api.annotations.common.SuppressWarnings(value={"DMI_COLLECTION_OF_URLS"}, justification="URLs have never host part") //NOI18N - public static Set getDependentRoots (final URL root) { - final Map> sourceDeps = IndexingController.getDefault().getRootDependencies(); - final Map> binaryDeps = IndexingController.getDefault().getBinaryRootDependencies(); - return getDependentRootsImpl (root, sourceDeps, binaryDeps, true); + @NonNull + @org.netbeans.api.annotations.common.SuppressWarnings(value = {"DMI_COLLECTION_OF_URLS"}, justification="URLs have never host part") + public static Set getDependentRoots (@NonNull final URL root) { + return getDependentRoots(root, true); } /** @@ -691,97 +688,19 @@ * root, never returns null. * @since 0.110 */ - @org.netbeans.api.annotations.common.SuppressWarnings(value = {"DMI_COLLECTION_OF_URLS"}, justification="URLs have never host part") //NOI18N - public static Set getDependentRoots(final URL root, boolean filterNonOpenedProjects) { - final Map> sourceDeps = IndexingController.getDefault().getRootDependencies(); - final Map> binaryDeps = IndexingController.getDefault().getBinaryRootDependencies(); - return getDependentRootsImpl(root, sourceDeps, binaryDeps, filterNonOpenedProjects); + @NonNull + @org.netbeans.api.annotations.common.SuppressWarnings(value = {"DMI_COLLECTION_OF_URLS"}, justification="URLs have never host part") + public static Set getDependentRoots( + @NonNull final URL root, + final boolean filterNonOpenedProjects) { + final FileObject rootFO = URLMapper.findFileObject(root); + if (rootFO != null) { + return mapToURLs(QuerySupport.findDependentRoots(rootFO,filterNonOpenedProjects)); + } else { + return Collections.singleton(root); + } } - - @org.netbeans.api.annotations.common.SuppressWarnings(value={"DMI_COLLECTION_OF_URLS"}, justification="URLs have never host part") //NOI18N - static Set getDependentRootsImpl (final URL root, final Map> sourceDeps, Map> binaryDeps, boolean filterNonOpenedProjects) { - Set urls; - - if (sourceDeps.containsKey(root)) { - urls = findReverseSourceRoots(root, sourceDeps); - } else { - FileObject rootFO = URLMapper.findFileObject(root); - - if (rootFO != null) { - urls = new HashSet(); - - for (URL binary : findBinaryRootsForSourceRoot(rootFO, binaryDeps)) { - List deps = binaryDeps.get(binary); - - if (deps != null) { - urls.addAll(deps); - } - } - } else { - urls = new HashSet(); - } - } - - if(filterNonOpenedProjects) { - Set cps = GlobalPathRegistry.getDefault().getPaths(ClassPath.SOURCE); - Set toRetain = new HashSet(); - for (ClassPath cp : cps) { - for (ClassPath.Entry e : cp.entries()) { - toRetain.add(e.getURL()); - } - } - urls.retainAll(toRetain); - } - return urls; - } - - private static Set findReverseSourceRoots(final URL thisSourceRoot, Map> deps) { - //Create inverse dependencies - final Map> inverseDeps = new HashMap> (); - for (Map.Entry> entry : deps.entrySet()) { - final URL u1 = entry.getKey(); - final List l1 = entry.getValue(); - for (URL u2 : l1) { - List l2 = inverseDeps.get(u2); - if (l2 == null) { - l2 = new ArrayList(); - inverseDeps.put (u2,l2); - } - l2.add (u1); - } - } - //Collect dependencies - final Set result = new HashSet(); - final LinkedList todo = new LinkedList (); - todo.add (thisSourceRoot); - while (!todo.isEmpty()) { - final URL u = todo.removeFirst(); - if (!result.contains(u)) { - result.add (u); - final List ideps = inverseDeps.get(u); - if (ideps != null) { - todo.addAll (ideps); - } - } - } - - return result; - } - - private static Set findBinaryRootsForSourceRoot(FileObject sourceRoot, Map> binaryDeps) { - Set result = new HashSet(); - - for (URL bin : binaryDeps.keySet()) { - for (FileObject s : SourceForBinaryQuery.findSourceRoots(bin).getRoots()) { - if (s == sourceRoot) { - result.add(bin); - } - } - } - - return result; - } - + //Helper methods /** @@ -1267,4 +1186,14 @@ return s.toLowerCase(); } } + + @NonNull + private static Set mapToURLs( + @NonNull final Collection fos) { + final Set res = new HashSet(fos.size()); + for (FileObject fo : fos) { + res.add(fo.toURL()); + } + return res; + } } diff --git a/parsing.api/apichanges.xml b/parsing.api/apichanges.xml --- a/parsing.api/apichanges.xml +++ b/parsing.api/apichanges.xml @@ -110,6 +110,22 @@ + + + Added QuerySupport.findDependentRoots to find out source roots depending on given source root. + + + + + +

+ Added a QuerySupport.findDependentRoots method returning the dependent source roots for given source root. + It returns all the source roots which have either direct or transitive dependency on the given source root. +

+
+ + +
Added EmbeddingProvider.Registration annotation to register EmbeddingProviders. diff --git a/parsing.api/nbproject/project.properties b/parsing.api/nbproject/project.properties --- a/parsing.api/nbproject/project.properties +++ b/parsing.api/nbproject/project.properties @@ -3,7 +3,7 @@ javac.source=1.6 javadoc.apichanges=${basedir}/apichanges.xml javadoc.arch=${basedir}/arch.xml -spec.version.base=1.63.0 +spec.version.base=1.64.0 test.config.stableBTD.includes=**/*Test.class test.config.stableBTD.excludes=\ diff --git a/parsing.api/src/org/netbeans/modules/parsing/spi/indexing/support/QuerySupport.java b/parsing.api/src/org/netbeans/modules/parsing/spi/indexing/support/QuerySupport.java --- a/parsing.api/src/org/netbeans/modules/parsing/spi/indexing/support/QuerySupport.java +++ b/parsing.api/src/org/netbeans/modules/parsing/spi/indexing/support/QuerySupport.java @@ -60,7 +60,11 @@ import java.util.concurrent.Callable; import java.util.logging.Level; import java.util.logging.Logger; +import org.netbeans.api.annotations.common.CheckForNull; +import org.netbeans.api.annotations.common.NonNull; import org.netbeans.api.java.classpath.ClassPath; +import org.netbeans.api.java.classpath.GlobalPathRegistry; +import org.netbeans.api.java.queries.SourceForBinaryQuery; import org.netbeans.api.project.FileOwnerQuery; import org.netbeans.api.project.Project; import org.netbeans.modules.parsing.impl.Installer; @@ -76,6 +80,7 @@ import org.netbeans.modules.parsing.impl.indexing.TransientUpdateSupport; import org.netbeans.modules.parsing.impl.indexing.URLCache; import org.netbeans.modules.parsing.impl.indexing.Util; +import org.netbeans.modules.parsing.impl.indexing.friendapi.IndexingController; import org.netbeans.modules.parsing.impl.indexing.lucene.LayeredDocumentIndex; import org.netbeans.modules.parsing.impl.indexing.lucene.LuceneIndexFactory; import org.netbeans.modules.parsing.lucene.support.DocumentIndex; @@ -83,6 +88,7 @@ import org.netbeans.modules.parsing.lucene.support.Queries; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileStateInvalidException; +import org.openide.filesystems.URLMapper; import org.openide.util.Parameters; /** @@ -155,6 +161,67 @@ } /** + * Returns the dependent source roots for given source root. It returns + * all the source roots which have either direct or transitive dependency on + * the given source root. + * + * @param root to find the dependent roots for + * @param filterNonOpenedProjects if true the results contains only roots of + * opened projects + * @return {@link Collection} of {@link FileObject}s containing at least the incoming + * root, never returns null. + * @since 1.64 + */ + @NonNull + @org.netbeans.api.annotations.common.SuppressWarnings(value={"DMI_COLLECTION_OF_URLS"}, justification="URLs have never host part") + public static Collection findDependentRoots( + @NonNull final FileObject file, + final boolean filterNonOpenedProjects) { + Parameters.notNull("file", file); //NOI18N + + final URL root = findOwnerRoot(file); + if (root == null) { + return Collections.emptySet(); + } + final IndexingController ic = IndexingController.getDefault(); + final Map> binaryDeps = ic.getBinaryRootDependencies(); + final Map> sourceDeps = ic.getRootDependencies(); + final Map> peerDeps = ic.getRootPeers(); + Set urls; + + if (sourceDeps.containsKey(root)) { + urls = findReverseSourceRoots(root, sourceDeps, peerDeps); + } else { + urls = new HashSet(); + final FileObject rootFo = URLMapper.findFileObject(root); + if (rootFo != null) { + for (URL binary : findBinaryRootsForSourceRoot(rootFo, binaryDeps)) { + List deps = binaryDeps.get(binary); + if (deps != null) { + urls.addAll(deps); + } + } + } + } + + if(filterNonOpenedProjects) { + final GlobalPathRegistry gpr = GlobalPathRegistry.getDefault(); + final Set cps = new HashSet(); + for (String id : PathRecognizerRegistry.getDefault().getSourceIds()) { + cps.addAll(gpr.getPaths(id)); + } + Set toRetain = new HashSet(); + for (ClassPath cp : cps) { + for (ClassPath.Entry e : cp.entries()) { + toRetain.add(e.getURL()); + } + } + urls.retainAll(toRetain); + } + return mapToFileObjects(urls); + } + + /** * Gets classpath roots relevant for a project. This method tries to find * classpaths with sourcePathIds, libraryPathIds and * binaryPathIds supplied by the project. @@ -470,7 +537,113 @@ case CASE_INSENSITIVE_CAMEL_CASE: return Queries.QueryKind.CASE_INSENSITIVE_CAMEL_CASE; default: throw new UnsupportedOperationException (kind.toString()); } - } + } + + @CheckForNull + private static URL findOwnerRoot(@NonNull final FileObject file) { + final PathRecognizerRegistry regs = PathRecognizerRegistry.getDefault(); + URL res = findOwnerRoot(file, regs.getSourceIds()); + if (res != null) { + return res; + } + res = findOwnerRoot(file, regs.getBinaryLibraryIds()); + if (res != null) { + return res; + } + res = findOwnerRoot(file, regs.getLibraryIds()); + if (res != null) { + return res; + } + //Fallback for roots with wrong classpath + return file.isFolder() ? file.toURL() : null; + } + + @CheckForNull + private static URL findOwnerRoot( + @NonNull final FileObject file, + @NonNull final Collection ids) { + for (String id : ids) { + final ClassPath cp = ClassPath.getClassPath(file, id); + if (cp != null) { + final FileObject owner = cp.findOwnerRoot(file); + if (owner != null) { + return owner.toURL(); + } + } + } + return null; + } + + @NonNull + @org.netbeans.api.annotations.common.SuppressWarnings(value={"DMI_COLLECTION_OF_URLS"}, justification="URLs have never host part") + private static Set findReverseSourceRoots( + @NonNull final URL thisSourceRoot, + @NonNull final Map> deps, + @NonNull final Map> peers) { + //Create inverse dependencies + final Map> inverseDeps = new HashMap> (); + for (Map.Entry> entry : deps.entrySet()) { + final URL u1 = entry.getKey(); + final List l1 = entry.getValue(); + for (URL u2 : l1) { + List l2 = inverseDeps.get(u2); + if (l2 == null) { + l2 = new ArrayList(); + inverseDeps.put (u2,l2); + } + l2.add (u1); + } + } + //Collect dependencies + final Set result = new HashSet(); + final LinkedList todo = new LinkedList (); + todo.add (thisSourceRoot); + while (!todo.isEmpty()) { + final URL u = todo.removeFirst(); + if (!result.contains(u)) { + result.add (u); + List ideps = inverseDeps.get(u); + if (ideps != null) { + todo.addAll (ideps); + } + ideps = peers.get(u); + if (ideps != null) { + todo.addAll (ideps); + } + } + } + + return result; + } + + @NonNull + @org.netbeans.api.annotations.common.SuppressWarnings(value={"DMI_COLLECTION_OF_URLS"}, justification="URLs have never host part") + private static Set findBinaryRootsForSourceRoot( + @NonNull final FileObject sourceRoot, + @NonNull final Map> binaryDeps) { + Set result = new HashSet(); + for (URL bin : binaryDeps.keySet()) { + for (FileObject fo : SourceForBinaryQuery.findSourceRoots(bin).getRoots()) { + if (sourceRoot.equals(fo)) { + result.add(bin); + } + } + } + return result; + } + + @NonNull + private static Collection mapToFileObjects( + @NonNull final Collection urls) { + final Collection result = new ArrayList(urls.size()); + for (URL u : urls) { + final FileObject fo = URLMapper.findFileObject(u); + if (fo != null) { + result.add(fo); + } + } + return result; + } /* test */ static final class IndexerQuery { diff --git a/parsing.api/test/unit/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdaterTest.java b/parsing.api/test/unit/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdaterTest.java --- a/parsing.api/test/unit/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdaterTest.java +++ b/parsing.api/test/unit/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdaterTest.java @@ -161,8 +161,8 @@ public class RepositoryUpdaterTest extends NbTestCase { - static final int TIME = Integer.getInteger("RepositoryUpdaterTest.timeout", 5000); //NOI18N - static final int NEGATIVE_TIME = Integer.getInteger("RepositoryUpdaterTest.negative-timeout", 5000); //NOI18N + public static final int TIME = Integer.getInteger("RepositoryUpdaterTest.timeout", 5000); //NOI18N + public static final int NEGATIVE_TIME = Integer.getInteger("RepositoryUpdaterTest.negative-timeout", 5000); //NOI18N private static final String SOURCES = "FOO_SOURCES"; private static final String PLATFORM = "FOO_PLATFORM"; private static final String LIBS = "FOO_LIBS"; @@ -335,7 +335,7 @@ } } - /* package */ static void waitForRepositoryUpdaterInit() throws Exception { + public static void waitForRepositoryUpdaterInit() throws Exception { RepositoryUpdater.getDefault().ignoreIndexerCacheEvents(true); RepositoryUpdater.getDefault().start(true); RepositoryUpdater.State state; diff --git a/parsing.api/test/unit/src/org/netbeans/modules/parsing/spi/indexing/support/QuerySupportTest.java b/parsing.api/test/unit/src/org/netbeans/modules/parsing/spi/indexing/support/QuerySupportTest.java new file mode 100644 --- /dev/null +++ b/parsing.api/test/unit/src/org/netbeans/modules/parsing/spi/indexing/support/QuerySupportTest.java @@ -0,0 +1,616 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle 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 2013 Sun Microsystems, Inc. + */ +package org.netbeans.modules.parsing.spi.indexing.support; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.swing.event.ChangeListener; +import org.netbeans.api.java.classpath.ClassPath; +import org.netbeans.api.java.classpath.GlobalPathRegistry; +import org.netbeans.api.java.queries.SourceForBinaryQuery; +import org.netbeans.junit.MockServices; +import org.netbeans.junit.NbTestCase; +import org.netbeans.modules.parsing.impl.indexing.Pair; +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdater; +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdaterTest; +import org.netbeans.modules.parsing.impl.indexing.friendapi.IndexingController; +import org.netbeans.modules.parsing.lucene.support.LowMemoryWatcher; +import org.netbeans.modules.parsing.spi.indexing.PathRecognizer; +import org.netbeans.spi.java.classpath.ClassPathProvider; +import org.netbeans.spi.java.classpath.support.ClassPathSupport; +import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation2; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; + +/** + * + * @author Tomas Zezula + */ +public class QuerySupportTest extends NbTestCase { + + private final Map> registeredClasspaths = new HashMap>(); + + public QuerySupportTest(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + clearWorkDir(); + MockServices.setServices( + JavaLikePathRecognizer.class, + ScriptingLikePathRecognizer.class, + ClassPathProviderImpl.class, + SourceForBinaryQueryImpl.class); + RepositoryUpdaterTest.waitForRepositoryUpdaterInit(); + } + + @Override + protected void tearDown() throws Exception { + for(String id : registeredClasspaths.keySet()) { + final Set classpaths = registeredClasspaths.get(id); + GlobalPathRegistry.getDefault().unregister(id, classpaths.toArray(new ClassPath[classpaths.size()])); + } + registeredClasspaths.clear(); + ClassPathProviderImpl.register(Collections.>emptyMap()); + SourceForBinaryQueryImpl.register(Collections.>>emptyMap()); + LowMemoryWatcher.getInstance().free(); + RepositoryUpdater.getDefault().waitUntilFinished(RepositoryUpdaterTest.TIME); + super.tearDown(); + } + + + + public void testGetDependentRootsJavaLikeDependenciesAllProjectsOpened() throws IOException, InterruptedException { + final FileObject wd = FileUtil.toFileObject(getWorkDir()); + final FileObject src1 = FileUtil.createFolder(wd,"src1"); //NOI18N + final URL build1 = FileUtil.urlForArchiveOrDir(new File (getWorkDir(),"build1"));//NOI18N + final FileObject src2 = FileUtil.createFolder(wd,"src2"); //NOI18N + final URL build2 = FileUtil.urlForArchiveOrDir(new File (getWorkDir(),"build2")); //NOI18N + final FileObject src3 = FileUtil.createFolder(wd,"src3"); //NOI18N + final URL build3 = FileUtil.urlForArchiveOrDir(new File (getWorkDir(),"build3")); //NOI18N + final FileObject src4 = FileUtil.createFolder(wd,"src4"); //NOI18N + final URL build4 = FileUtil.urlForArchiveOrDir(new File (getWorkDir(),"build4")); //NOI18N + + final ClassPath src1Source = ClassPathSupport.createClassPath(src1); + final ClassPath src2Source = ClassPathSupport.createClassPath(src2); + final ClassPath src2Compile = ClassPathSupport.createClassPath(build1); + final ClassPath src3Source = ClassPathSupport.createClassPath(src3); + final ClassPath src3Compile = ClassPathSupport.createClassPath(build1); + final ClassPath src4Source = ClassPathSupport.createClassPath(src4); + final ClassPath src4Compile = ClassPathSupport.createClassPath(build2); + + final Map>> sfbq = new HashMap>>(); + sfbq.put(build1,Pair.of(true,Collections.singletonList(src1))); + sfbq.put(build2,Pair.of(true,Collections.singletonList(src2))); + sfbq.put(build3,Pair.of(true,Collections.singletonList(src3))); + sfbq.put(build4,Pair.of(true,Collections.singletonList(src4))); + SourceForBinaryQueryImpl.register(sfbq); + + + final ClassPath boot = ClassPath.EMPTY; + final Map src1cps = new HashMap(); + src1cps.put(JavaLikePathRecognizer.BOOT, boot); + src1cps.put(JavaLikePathRecognizer.COMPILE, ClassPath.EMPTY); + src1cps.put(JavaLikePathRecognizer.SRC, src1Source); + final Map src2cps = new HashMap(); + src2cps.put(JavaLikePathRecognizer.BOOT, boot); + src2cps.put(JavaLikePathRecognizer.COMPILE, src2Compile); + src2cps.put(JavaLikePathRecognizer.SRC, src2Source); + final Map src3cps = new HashMap(); + src3cps.put(JavaLikePathRecognizer.BOOT, boot); + src3cps.put(JavaLikePathRecognizer.COMPILE, src3Compile); + src3cps.put(JavaLikePathRecognizer.SRC, src3Source); + final Map src4cps = new HashMap(); + src4cps.put(JavaLikePathRecognizer.BOOT, boot); + src4cps.put(JavaLikePathRecognizer.COMPILE, src4Compile); + src4cps.put(JavaLikePathRecognizer.SRC, src4Source); + final Map> cps = new HashMap>(); + cps.put(src1,src1cps); + cps.put(src2,src2cps); + cps.put(src3,src3cps); + cps.put(src4,src4cps); + ClassPathProviderImpl.register(cps); + + globalPathRegistry_register( + JavaLikePathRecognizer.BOOT, + new ClassPath[]{ + boot + }); + globalPathRegistry_register( + JavaLikePathRecognizer.COMPILE, + new ClassPath[]{ + src2Compile, + src3Compile, + src4Compile + }); + globalPathRegistry_register( + JavaLikePathRecognizer.SRC, + new ClassPath[]{ + src1Source, + src2Source, + src3Source, + src4Source + }); + + RepositoryUpdater.getDefault().waitUntilFinished(RepositoryUpdaterTest.TIME); + assertEquals( + IndexingController.getDefault().getRootDependencies().keySet().toString(), + 4, + IndexingController.getDefault().getRootDependencies().size()); + + assertEquals(new FileObject[] {src4}, QuerySupport.findDependentRoots(src4, true)); + assertEquals(new FileObject[] {src3}, QuerySupport.findDependentRoots(src3, true)); + assertEquals(new FileObject[] {src2, src4}, QuerySupport.findDependentRoots(src2, true)); + assertEquals(new FileObject[] {src1, src2, src3, src4}, QuerySupport.findDependentRoots(src1, true)); + + + assertEquals(new FileObject[] {src4}, QuerySupport.findDependentRoots(src4, false)); + assertEquals(new FileObject[] {src3}, QuerySupport.findDependentRoots(src3, false)); + assertEquals(new FileObject[] {src2, src4}, QuerySupport.findDependentRoots(src2, false)); + assertEquals(new FileObject[] {src1, src2, src3, src4}, QuerySupport.findDependentRoots(src1, false)); + } + + + public void testGetDependentRootsJavaLikeDependenciesProjectsClosed() throws IOException, InterruptedException { + final FileObject wd = FileUtil.toFileObject(getWorkDir()); + final FileObject src1 = FileUtil.createFolder(wd,"src1"); //NOI18N + final URL build1 = FileUtil.urlForArchiveOrDir(new File (getWorkDir(),"build1"));//NOI18N + final FileObject src2 = FileUtil.createFolder(wd,"src2"); //NOI18N + final URL build2 = FileUtil.urlForArchiveOrDir(new File (getWorkDir(),"build2")); //NOI18N + final FileObject src3 = FileUtil.createFolder(wd,"src3"); //NOI18N + final URL build3 = FileUtil.urlForArchiveOrDir(new File (getWorkDir(),"build3")); //NOI18N + final FileObject src4 = FileUtil.createFolder(wd,"src4"); //NOI18N + final URL build4 = FileUtil.urlForArchiveOrDir(new File (getWorkDir(),"build4")); //NOI18N + + final ClassPath src1Source = ClassPathSupport.createClassPath(src1); + final ClassPath src2Source = ClassPathSupport.createClassPath(src2); + final ClassPath src2Compile = ClassPathSupport.createClassPath(build1); + final ClassPath src3Source = ClassPathSupport.createClassPath(src3); + final ClassPath src3Compile = ClassPathSupport.createClassPath(build1); + final ClassPath src4Source = ClassPathSupport.createClassPath(src4); + final ClassPath src4Compile = ClassPathSupport.createClassPath(build2); + + final Map>> sfbq = new HashMap>>(); + sfbq.put(build1,Pair.of(true,Collections.singletonList(src1))); + sfbq.put(build2,Pair.of(true,Collections.singletonList(src2))); + sfbq.put(build3,Pair.of(true,Collections.singletonList(src3))); + sfbq.put(build4,Pair.of(true,Collections.singletonList(src4))); + SourceForBinaryQueryImpl.register(sfbq); + + + final ClassPath boot = ClassPath.EMPTY; + final Map src1cps = new HashMap(); + src1cps.put(JavaLikePathRecognizer.BOOT, boot); + src1cps.put(JavaLikePathRecognizer.COMPILE, ClassPath.EMPTY); + src1cps.put(JavaLikePathRecognizer.SRC, src1Source); + final Map src2cps = new HashMap(); + src2cps.put(JavaLikePathRecognizer.BOOT, boot); + src2cps.put(JavaLikePathRecognizer.COMPILE, src2Compile); + src2cps.put(JavaLikePathRecognizer.SRC, src2Source); + final Map src3cps = new HashMap(); + src3cps.put(JavaLikePathRecognizer.BOOT, boot); + src3cps.put(JavaLikePathRecognizer.COMPILE, src3Compile); + src3cps.put(JavaLikePathRecognizer.SRC, src3Source); + final Map src4cps = new HashMap(); + src4cps.put(JavaLikePathRecognizer.BOOT, boot); + src4cps.put(JavaLikePathRecognizer.COMPILE, src4Compile); + src4cps.put(JavaLikePathRecognizer.SRC, src4Source); + final Map> cps = new HashMap>(); + cps.put(src1,src1cps); + cps.put(src2,src2cps); + cps.put(src3,src3cps); + cps.put(src4,src4cps); + ClassPathProviderImpl.register(cps); + + globalPathRegistry_register( + JavaLikePathRecognizer.BOOT, + new ClassPath[]{ + boot + }); + globalPathRegistry_register( + JavaLikePathRecognizer.COMPILE, + new ClassPath[]{ + src4Compile + }); + globalPathRegistry_register( + JavaLikePathRecognizer.SRC, + new ClassPath[]{ + src4Source + }); + + RepositoryUpdater.getDefault().waitUntilFinished(RepositoryUpdaterTest.TIME); + assertEquals( + IndexingController.getDefault().getRootDependencies().keySet().toString(), + 3, + IndexingController.getDefault().getRootDependencies().size()); + + assertEquals(new FileObject[] {src4}, QuerySupport.findDependentRoots(src4, true)); + assertEquals(new FileObject[] {src4}, QuerySupport.findDependentRoots(src2, true)); + assertEquals(new FileObject[] {src4}, QuerySupport.findDependentRoots(src1, true)); + + + assertEquals(new FileObject[] {src4}, QuerySupport.findDependentRoots(src4, false)); + assertEquals(new FileObject[] {src2, src4}, QuerySupport.findDependentRoots(src2, false)); + assertEquals(new FileObject[] {src1, src2, src4}, QuerySupport.findDependentRoots(src1, false)); + } + + + public void testGetDependentRootsJavaLikeBinaryDependencies() throws IOException, InterruptedException { + + IndexingController.getDefault().getRootDependencies().keySet(); + + final FileObject wd = FileUtil.toFileObject(getWorkDir()); + final FileObject bin1 = FileUtil.createFolder(wd, "bin1"); //NOI18N + final FileObject bin1Sources = FileUtil.createFolder(wd, "bin1src"); //NOI18N + final FileObject src1 = FileUtil.createFolder(wd,"src1"); //NOI18N + final FileObject src2 = FileUtil.createFolder(wd,"src2"); //NOI18N + final FileObject src3 = FileUtil.createFolder(wd,"src3"); //NOI18N + + final ClassPath src1Source = ClassPathSupport.createClassPath(src1); + final ClassPath src1Compile = ClassPathSupport.createClassPath(bin1); + final ClassPath src2Source = ClassPathSupport.createClassPath(src2); + final ClassPath src2Compile = ClassPathSupport.createClassPath(bin1); + final ClassPath src3Source = ClassPathSupport.createClassPath(src3); + + final Map>> sfbq = new HashMap>>(); + sfbq.put(bin1.toURL(),Pair.of(false,Collections.singletonList(bin1Sources))); + SourceForBinaryQueryImpl.register(sfbq); + + + final ClassPath boot = ClassPath.EMPTY; + final Map src1cps = new HashMap(); + src1cps.put(JavaLikePathRecognizer.BOOT, boot); + src1cps.put(JavaLikePathRecognizer.COMPILE, src1Compile); + src1cps.put(JavaLikePathRecognizer.SRC, src1Source); + final Map src2cps = new HashMap(); + src2cps.put(JavaLikePathRecognizer.BOOT, boot); + src2cps.put(JavaLikePathRecognizer.COMPILE, src2Compile); + src2cps.put(JavaLikePathRecognizer.SRC, src2Source); + final Map src3cps = new HashMap(); + src3cps.put(JavaLikePathRecognizer.BOOT, boot); + src3cps.put(JavaLikePathRecognizer.COMPILE, ClassPath.EMPTY); + src3cps.put(JavaLikePathRecognizer.SRC, src3Source); + final Map> cps = new HashMap>(); + cps.put(src1,src1cps); + cps.put(src2,src2cps); + cps.put(src3,src3cps); + ClassPathProviderImpl.register(cps); + + globalPathRegistry_register( + JavaLikePathRecognizer.BOOT, + new ClassPath[]{ + boot + }); + globalPathRegistry_register( + JavaLikePathRecognizer.COMPILE, + new ClassPath[]{ + src1Compile, + src2Compile + }); + globalPathRegistry_register( + JavaLikePathRecognizer.SRC, + new ClassPath[]{ + src1Source, + src2Source, + src3Source + }); + + RepositoryUpdater.getDefault().waitUntilFinished(RepositoryUpdaterTest.TIME); + assertEquals( + IndexingController.getDefault().getRootDependencies().keySet().toString(), + 3, + IndexingController.getDefault().getRootDependencies().size()); + + assertEquals(new FileObject[] {src1, src2}, QuerySupport.findDependentRoots(bin1Sources, true)); + } + + public void testGetDependentRootsJavaLikeDependenciesWithPeerRoots() throws IOException, InterruptedException { + final FileObject wd = FileUtil.toFileObject(getWorkDir()); + final FileObject src1a = FileUtil.createFolder(wd,"src1a"); //NOI18N + final FileObject src1b = FileUtil.createFolder(wd,"src1b"); //NOI18N + + final ClassPath src1Source = ClassPathSupport.createClassPath(src1a, src1b); + + + final ClassPath boot = ClassPath.EMPTY; + final Map src1cps = new HashMap(); + src1cps.put(JavaLikePathRecognizer.BOOT, boot); + src1cps.put(JavaLikePathRecognizer.COMPILE, ClassPath.EMPTY); + src1cps.put(JavaLikePathRecognizer.SRC, src1Source); + final Map> cps = new HashMap>(); + cps.put(src1a,src1cps); + cps.put(src1b,src1cps); + ClassPathProviderImpl.register(cps); + + globalPathRegistry_register( + JavaLikePathRecognizer.BOOT, + new ClassPath[]{ + boot + }); + globalPathRegistry_register( + JavaLikePathRecognizer.SRC, + new ClassPath[]{ + src1Source + }); + + RepositoryUpdater.getDefault().waitUntilFinished(RepositoryUpdaterTest.TIME); + assertEquals( + IndexingController.getDefault().getRootDependencies().keySet().toString(), + 2, + IndexingController.getDefault().getRootDependencies().size()); + + assertEquals(new FileObject[] {src1a, src1b}, QuerySupport.findDependentRoots(src1a, true)); + assertEquals(new FileObject[] {src1a, src1b}, QuerySupport.findDependentRoots(src1b, true)); + + assertEquals(new FileObject[] {src1a, src1b}, QuerySupport.findDependentRoots(src1a, false)); + assertEquals(new FileObject[] {src1a, src1b}, QuerySupport.findDependentRoots(src1b, false)); + } + + public void testGetDependentRootsScriptingLikeDependenciesAllProjectsOpened() throws IOException, InterruptedException { + final FileObject wd = FileUtil.toFileObject(getWorkDir()); + final FileObject libSrc = FileUtil.createFolder(wd,"libSrc"); //NOI18N + final FileObject src1 = FileUtil.createFolder(wd,"src1"); //NOI18N + final FileObject src2 = FileUtil.createFolder(wd,"src2"); //NOI18N + final FileObject src3 = FileUtil.createFolder(wd,"src3"); //NOI18N + final FileObject src4 = FileUtil.createFolder(wd,"src4"); //NOI18N + + final ClassPath src1Source = ClassPathSupport.createClassPath(src1); + final ClassPath src1Compile = ClassPathSupport.createClassPath(libSrc); + final ClassPath src2Source = ClassPathSupport.createClassPath(src2); + final ClassPath src2Compile = ClassPathSupport.createClassPath(src1); + final ClassPath src3Source = ClassPathSupport.createClassPath(src3); + final ClassPath src3Compile = ClassPathSupport.createClassPath(src1); + final ClassPath src4Source = ClassPathSupport.createClassPath(src4); + final ClassPath src4Compile = ClassPathSupport.createClassPath(src2); + + + final Map src1cps = new HashMap(); + src1cps.put(ScriptingLikePathRecognizer.COMPILE, src1Compile); + src1cps.put(ScriptingLikePathRecognizer.SRC, src1Source); + final Map src2cps = new HashMap(); + src2cps.put(ScriptingLikePathRecognizer.COMPILE, src2Compile); + src2cps.put(ScriptingLikePathRecognizer.SRC, src2Source); + final Map src3cps = new HashMap(); + src3cps.put(ScriptingLikePathRecognizer.COMPILE, src3Compile); + src3cps.put(ScriptingLikePathRecognizer.SRC, src3Source); + final Map src4cps = new HashMap(); + src4cps.put(ScriptingLikePathRecognizer.COMPILE, src4Compile); + src4cps.put(ScriptingLikePathRecognizer.SRC, src4Source); + final Map> cps = new HashMap>(); + cps.put(src1,src1cps); + cps.put(src2,src2cps); + cps.put(src3,src3cps); + cps.put(src4,src4cps); + ClassPathProviderImpl.register(cps); + + globalPathRegistry_register( + ScriptingLikePathRecognizer.COMPILE, + new ClassPath[]{ + src2Compile, + src3Compile, + src4Compile + }); + globalPathRegistry_register( + ScriptingLikePathRecognizer.SRC, + new ClassPath[]{ + src1Source, + src2Source, + src3Source, + src4Source + }); + + RepositoryUpdater.getDefault().waitUntilFinished(RepositoryUpdaterTest.TIME); + assertEquals( + IndexingController.getDefault().getRootDependencies().keySet().toString(), + 5, + IndexingController.getDefault().getRootDependencies().size()); + + assertEquals(new FileObject[] {src4}, QuerySupport.findDependentRoots(src4, true)); + assertEquals(new FileObject[] {src3}, QuerySupport.findDependentRoots(src3, true)); + assertEquals(new FileObject[] {src2, src4}, QuerySupport.findDependentRoots(src2, true)); + assertEquals(new FileObject[] {src1, src2, src3, src4}, QuerySupport.findDependentRoots(src1, true)); + assertEquals(new FileObject[] {src1, src2, src3, src4}, QuerySupport.findDependentRoots(libSrc, true)); + + assertEquals(new FileObject[] {src4}, QuerySupport.findDependentRoots(src4, false)); + assertEquals(new FileObject[] {src3}, QuerySupport.findDependentRoots(src3, false)); + assertEquals(new FileObject[] {src2, src4}, QuerySupport.findDependentRoots(src2, false)); + assertEquals(new FileObject[] {src1, src2, src3, src4}, QuerySupport.findDependentRoots(src1, false)); + assertEquals(new FileObject[] {libSrc, src1, src2, src3, src4}, QuerySupport.findDependentRoots(libSrc, false)); + } + + private void assertEquals(FileObject[] expected, Collection res) { + final Set set = new HashSet(); + Collections.addAll(set, expected); + for (FileObject fo : res) { + assertTrue( + String.format("expected: %s res: %s", Arrays.toString(expected), res), //NOI18N + set.remove(fo)); + } + assertTrue( + String.format("expected: %s res: %s", Arrays.toString(expected), res), //NOI8N + set.isEmpty()); + } + + private void globalPathRegistry_register(String id, ClassPath [] classpaths) { + Set set = registeredClasspaths.get(id); + if (set == null) { + set = Collections.newSetFromMap(new IdentityHashMap()); + registeredClasspaths.put(id, set); + } + for (ClassPath cp : classpaths) { + set.add(cp); + } + GlobalPathRegistry.getDefault().register(id, classpaths); + } + + public static final class JavaLikePathRecognizer extends PathRecognizer { + + public static final String SRC = "source"; //NOI18N + public static final String COMPILE = "compile"; //NOI18N + public static final String BOOT = "boot"; //NOI18N + public static final String MIME_JAVA = "text/x-java"; //NOI18N + + @Override + public Set getSourcePathIds() { + return Collections.singleton(SRC); + } + + @Override + public Set getLibraryPathIds() { + return Collections.emptySet(); + } + + @Override + public Set getBinaryLibraryPathIds() { + return new HashSet(Arrays.asList(BOOT, COMPILE)); + } + + @Override + public Set getMimeTypes() { + return Collections.singleton(MIME_JAVA); + } + + } + + public static final class ScriptingLikePathRecognizer extends PathRecognizer { + + public static final String SRC = "scripts"; //NOI18N + public static final String COMPILE = "included"; //NOI18N + public static final String MIME_JAVA = "text/x-script"; //NOI18N + + @Override + public Set getSourcePathIds() { + return Collections.singleton(SRC); + } + + @Override + public Set getLibraryPathIds() { + return Collections.singleton(COMPILE); + } + + @Override + public Set getBinaryLibraryPathIds() { + return Collections.emptySet(); + } + + @Override + public Set getMimeTypes() { + return Collections.singleton(MIME_JAVA); + } + + } + + public static final class ClassPathProviderImpl implements ClassPathProvider { + + private static volatile Map> cps = Collections.emptyMap(); + + @Override + public ClassPath findClassPath(FileObject file, String type) { + for (Map.Entry> e : cps.entrySet()) { + if (e.getKey().equals(file) || FileUtil.isParentOf(e.getKey(), file)) { + return e.getValue().get(type); + } + } + return null; + } + + static void register(Map> newClassPaths) { + cps = newClassPaths; + } + + } + + public static final class SourceForBinaryQueryImpl implements SourceForBinaryQueryImplementation2 { + + private static volatile Map>> mapping = Collections.emptyMap(); + + @Override + public Result findSourceRoots2(final URL binaryRoot) { + final Pair> sources = mapping.get(binaryRoot); + if (sources == null) { + return null; + } + return new Result() { + @Override + public boolean preferSources() { + return sources.first; + } + + @Override + public FileObject[] getRoots() { + return sources.second.toArray(new FileObject[sources.second.size()]); + } + + @Override + public void addChangeListener(ChangeListener l) { + } + + @Override + public void removeChangeListener(ChangeListener l) { + } + }; + } + + @Override + public SourceForBinaryQuery.Result findSourceRoots(URL binaryRoot) { + return findSourceRoots2(binaryRoot); + } + + static void register(Map>> newMapping) { + mapping = newMapping; + } + + } + +}