# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: /space/jarda/netbeans/ergonomics/parsing.api # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: test/unit/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdaterExternalChangesTest.java --- test/unit/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdaterExternalChangesTest.java Base (BASE) +++ test/unit/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdaterExternalChangesTest.java Locally New @@ -0,0 +1,332 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 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 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.parsing.impl.indexing; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.net.URL; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.netbeans.api.editor.mimelookup.MimePath; +import org.netbeans.api.editor.mimelookup.test.MockMimeLookup; +import org.netbeans.api.java.classpath.ClassPath; +import org.netbeans.api.java.classpath.GlobalPathRegistry; +import org.netbeans.junit.MockServices; +import org.netbeans.junit.NbTestCase; +import org.netbeans.modules.parsing.impl.indexing.PathRegistryTest.FooPathRecognizer; +import org.netbeans.modules.parsing.impl.indexing.PathRegistryTest.OpenProject; +import org.netbeans.modules.parsing.impl.indexing.PathRegistryTest.SFBQImpl; +import org.netbeans.spi.java.classpath.ClassPathFactory; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdater.*; +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdaterTest.BinIndexerFactory; +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdaterTest.EmbIndexerFactory; +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdaterTest.EmbIndexerFactory; +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdaterTest.EmbParserFactory; +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdaterTest.EmbPathRecognizer; +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdaterTest.FooIndexerFactory; +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdaterTest.MutableClassPathImplementation; +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdaterTest.TestHandler; + +/** + * TODO: + * - test that modifying .zip/.jar triggeres rescan of this binary + * + * @author Tomas Zezula + */ +public class RepositoryUpdaterExternalChangesTest extends NbTestCase { + + private static final int TIME = 5000; + private static final String SOURCES = "FOO_SOURCES"; + private static final String PLATFORM = "FOO_PLATFORM"; + private static final String LIBS = "FOO_LIBS"; + private static final String MIME = "text/foo"; + private static final String EMIME = "text/emb"; + private static final String JARMIME = "application/java-archive"; + + private FileObject srcRoot1; + private FileObject srcRoot2; + private FileObject srcRoot3; + private FileObject compRoot1; + private FileObject compRoot2; + private FileObject bootRoot1; + private FileObject bootRoot2; + private FileObject bootRoot3; + private FileObject compSrc1; + private FileObject compSrc2; + private FileObject bootSrc1; + private FileObject unknown1; + private FileObject unknown2; + private FileObject unknownSrc2; + private FileObject srcRootWithFiles1; + + FileObject f3; + + private URL[] customFiles; + private URL[] embeddedFiles; + + private final BinIndexerFactory binIndexerFactory = new BinIndexerFactory(); +// Binary indexer have to be registered for MimePath.EMPTY, no mime-type specific binary indexers +// private final BinIndexerFactory jarIndexerFactory = new BinIndexerFactory(); + private final FooIndexerFactory indexerFactory = new FooIndexerFactory(); + private final EmbIndexerFactory eindexerFactory = new EmbIndexerFactory(); + + private final Map> registeredClasspaths = new HashMap>(); + + public RepositoryUpdaterExternalChangesTest (String name) { + super (name); + } + + @Override + protected void setUp() throws Exception { +// TopLogging.initializeQuietly(); + super.setUp(); + this.clearWorkDir(); + final File _wd = this.getWorkDir(); + final FileObject wd = FileUtil.toFileObject(_wd); + final FileObject cache = wd.createFolder("cache"); + CacheFolder.setCacheFolder(cache); + + MockServices.setServices(FooPathRecognizer.class, EmbPathRecognizer.class, SFBQImpl.class, OpenProject.class); + MockMimeLookup.setInstances(MimePath.EMPTY, binIndexerFactory); +// MockMimeLookup.setInstances(MimePath.get(JARMIME), jarIndexerFactory); + MockMimeLookup.setInstances(MimePath.get(MIME), indexerFactory); + MockMimeLookup.setInstances(MimePath.get(EMIME), eindexerFactory, new EmbParserFactory()); + Set mt = new HashSet(); + mt.add(EMIME); + mt.add(MIME); + Util.allMimeTypes = mt; + + assertNotNull("No masterfs",wd); + srcRoot1 = wd.createFolder("src1"); + assertNotNull(srcRoot1); + srcRoot2 = wd.createFolder("src2"); + assertNotNull(srcRoot2); + srcRoot3 = wd.createFolder("src3"); + assertNotNull (srcRoot3); + compRoot1 = wd.createFolder("comp1"); + assertNotNull (compRoot1); + compRoot2 = wd.createFolder("comp2"); + assertNotNull (compRoot2); + bootRoot1 = wd.createFolder("boot1"); + assertNotNull (bootRoot1); + bootRoot2 = wd.createFolder("boot2"); + assertNotNull (bootRoot2); + FileUtil.setMIMEType("jar", JARMIME); + FileObject jarFile = FileUtil.toFileObject(getDataDir()).getFileObject("JavaApplication1.jar"); + assertNotNull(jarFile); + assertTrue(FileUtil.isArchiveFile(jarFile)); + bootRoot3 = FileUtil.getArchiveRoot(jarFile); + assertNotNull (bootRoot3); + compSrc1 = wd.createFolder("cs1"); + assertNotNull (compSrc1); + compSrc2 = wd.createFolder("cs2"); + assertNotNull (compSrc2); + bootSrc1 = wd.createFolder("bs1"); + assertNotNull (bootSrc1); + unknown1 = wd.createFolder("uknw1"); + assertNotNull (unknown1); + unknown2 = wd.createFolder("uknw2"); + assertNotNull (unknown2); + unknownSrc2 = wd.createFolder("uknwSrc2"); + assertNotNull(unknownSrc2); + SFBQImpl.register (bootRoot1,bootSrc1); + SFBQImpl.register (compRoot1,compSrc1); + SFBQImpl.register (compRoot2,compSrc2); + SFBQImpl.register (unknown2,unknownSrc2); + + srcRootWithFiles1 = wd.createFolder("srcwf1"); + assertNotNull(srcRootWithFiles1); + FileUtil.setMIMEType("foo", MIME); + FileObject f1 = FileUtil.createData(srcRootWithFiles1,"folder/a.foo"); + assertNotNull(f1); + assertEquals(MIME, f1.getMIMEType()); + FileObject f2 = FileUtil.createData(srcRootWithFiles1,"folder/b.foo"); + assertNotNull(f2); + assertEquals(MIME, f2.getMIMEType()); + customFiles = new URL[] {f1.getURL(), f2.getURL()}; + + FileUtil.setMIMEType("emb", EMIME); + f3 = FileUtil.createData(srcRootWithFiles1,"folder/a.emb"); + assertNotNull(f3); + assertEquals(EMIME, f3.getMIMEType()); + FileObject f4 = FileUtil.createData(srcRootWithFiles1,"folder/b.emb"); + assertNotNull(f4); + assertEquals(EMIME, f4.getMIMEType()); + embeddedFiles = new URL[] {f3.getURL(), f4.getURL()}; + + waitForRepositoryUpdaterInit(); + } + + @Override + protected void tearDown() throws Exception { + for(String id : registeredClasspaths.keySet()) { + Set classpaths = registeredClasspaths.get(id); + GlobalPathRegistry.getDefault().unregister(id, classpaths.toArray(new ClassPath[classpaths.size()])); + } + + super.tearDown(); + } + + protected final void globalPathRegistry_register(String id, ClassPath [] classpaths) { + Set set = registeredClasspaths.get(id); + if (set == null) { + set = new HashSet(); + registeredClasspaths.put(id, set); + } + set.addAll(Arrays.asList(classpaths)); + GlobalPathRegistry.getDefault().register(id, classpaths); + } + + protected final void globalPathRegistry_unregister(String id, ClassPath [] classpaths) { + GlobalPathRegistry.getDefault().unregister(id, classpaths); + Set set = registeredClasspaths.get(id); + if (set != null) { + set.removeAll(Arrays.asList(classpaths)); + } + } + + /* package */ static void waitForRepositoryUpdaterInit() throws Exception { + RepositoryUpdaterTest.waitForRepositoryUpdaterInit();; + } + + public void testFileChanges() throws Exception { + final TestHandler handler = new TestHandler(); + final Logger logger = Logger.getLogger(RepositoryUpdater.class.getName()+".tests"); + logger.setLevel (Level.FINEST); + logger.addHandler(handler); + indexerFactory.indexer.setExpectedFile(customFiles, new URL[0], new URL[0]); + eindexerFactory.indexer.setExpectedFile(embeddedFiles, new URL[0], new URL[0]); + MutableClassPathImplementation mcpi1 = new MutableClassPathImplementation (); + mcpi1.addResource(this.srcRootWithFiles1); + ClassPath cp1 = ClassPathFactory.createClassPath(mcpi1); + globalPathRegistry_register(SOURCES,new ClassPath[]{cp1}); + assertTrue (handler.await()); + assertEquals(0, handler.getBinaries().size()); + assertEquals(1, handler.getSources().size()); + assertEquals(this.srcRootWithFiles1.getURL(), handler.getSources().get(0)); + assertTrue(indexerFactory.indexer.awaitIndex()); + assertTrue(eindexerFactory.indexer.awaitIndex()); + + //Test modifications + indexerFactory.indexer.setExpectedFile(new URL[0], new URL[0], new URL[0]); + eindexerFactory.indexer.setExpectedFile(new URL[]{f3.getURL()}, new URL[0], new URL[0]); + + File f = FileUtil.toFile(f3); + Reference ref = new WeakReference(f3); + f3 = null; + assertGC("File object can disappear", ref); + + final OutputStream out = new FileOutputStream(f); + try { + out.write(0); + } finally { + out.close(); + } + + simulateUserRefreshGesture(); + + assertTrue(indexerFactory.indexer.awaitIndex()); + assertTrue(eindexerFactory.indexer.awaitIndex()); + assertEquals(1, eindexerFactory.indexer.indexCounter); + + //Test file creation + final File container = f.getParentFile(); + File newFile = new File (container,"c.emb"); + indexerFactory.indexer.setExpectedFile(new URL[0], new URL[0], new URL[0]); + eindexerFactory.indexer.setExpectedFile(new URL[]{newFile.toURI().toURL()}, new URL[0], new URL[0]); + newFile.createNewFile(); + simulateUserRefreshGesture(); + + assertTrue(indexerFactory.indexer.awaitIndex()); + assertTrue(eindexerFactory.indexer.awaitIndex()); + assertEquals(1, eindexerFactory.indexer.indexCounter); + + //Test folder creation + File newFolder = new File (container,"subfolder"); + newFile = new File (newFolder,"d.emb"); + File newFile2 = new File (newFolder,"e.emb"); + indexerFactory.indexer.setExpectedFile(new URL[0], new URL[0], new URL[0]); + eindexerFactory.indexer.setExpectedFile(new URL[]{newFile.toURI().toURL(), newFile2.toURI().toURL()}, new URL[0], new URL[0]); + newFolder.mkdirs(); + touchFile (newFile); + touchFile (newFile2); + assertEquals(2,newFolder.list().length); + simulateUserRefreshGesture(); + assertTrue(indexerFactory.indexer.awaitIndex()); + assertTrue(eindexerFactory.indexer.awaitIndex()); + assertEquals(2, eindexerFactory.indexer.indexCounter); + + //Test file deleted + handler.reset(TestHandler.Type.DELETE); + indexerFactory.indexer.setExpectedFile(new URL[0], new URL[0], new URL[0]); + eindexerFactory.indexer.setExpectedFile(new URL[0], new URL[]{f3.getURL()}, new URL[0]); + f.delete(); + simulateUserRefreshGesture(); + assertTrue (handler.await()); + assertTrue(indexerFactory.indexer.awaitDeleted()); + assertTrue(eindexerFactory.indexer.awaitDeleted()); + assertEquals(0, eindexerFactory.indexer.indexCounter); + assertEquals(0,eindexerFactory.indexer.expectedDeleted.size()); + assertEquals(0, eindexerFactory.indexer.expectedDirty.size()); + } + + + private void touchFile (final File file) throws IOException { + OutputStream out = new FileOutputStream (file); + out.close(); + } + + private void simulateUserRefreshGesture() { + FileUtil.refreshAll(); + } + + +} Index: test/unit/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdaterTest.java --- test/unit/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdaterTest.java Base (BASE) +++ test/unit/src/org/netbeans/modules/parsing/impl/indexing/RepositoryUpdaterTest.java Locally Modified (Based On LOCAL) @@ -1069,7 +1069,7 @@ } - private static class BinIndexerFactory extends BinaryIndexerFactory { + static class BinIndexerFactory extends BinaryIndexerFactory { private final BinIndexer indexer = new BinIndexer(); @@ -1120,9 +1120,9 @@ } } - private static class FooIndexerFactory extends CustomIndexerFactory { + static class FooIndexerFactory extends CustomIndexerFactory { - private final FooIndexer indexer = new FooIndexer(); + final FooIndexer indexer = new FooIndexer(); @Override public CustomIndexer createIndexer() { @@ -1167,7 +1167,7 @@ } } - private static class FooIndexer extends CustomIndexer { + static class FooIndexer extends CustomIndexer { private Set expectedIndex = new HashSet(); private CountDownLatch indexFilesLatch; @@ -1230,9 +1230,9 @@ } } - private static class EmbIndexerFactory extends EmbeddingIndexerFactory { + static class EmbIndexerFactory extends EmbeddingIndexerFactory { - private EmbIndexer indexer = new EmbIndexer (); + EmbIndexer indexer = new EmbIndexer (); @Override public EmbeddingIndexer createIndexer(final Indexable indexable, final Snapshot snapshot) { @@ -1272,17 +1272,17 @@ } } - private static class EmbIndexer extends EmbeddingIndexer { + static class EmbIndexer extends EmbeddingIndexer { private Set expectedIndex = new HashSet(); private CountDownLatch indexFilesLatch; private CountDownLatch deletedFilesLatch; private CountDownLatch dirtyFilesLatch; - private volatile int indexCounter; + volatile int indexCounter; private volatile int deletedCounter; private volatile int dirtyCounter; - private Set expectedDeleted = new HashSet(); - private Set expectedDirty = new HashSet(); + Set expectedDeleted = new HashSet(); + Set expectedDirty = new HashSet(); public void setExpectedFile (URL[] files, URL[] deleted, URL[] dirty) { expectedIndex.clear(); @@ -1339,7 +1339,7 @@ } - private static class EmbParserFactory extends ParserFactory { + static class EmbParserFactory extends ParserFactory { @Override public Parser createParser(Collection snapshots) {