# HG changeset patch # User Vladimir Kvashin # Date 1301295939 -14400 # Node ID ca06d70d6631700b16945bb5d3a0dbf21a0beff4 # Parent ca82aebf81613a582b47c8394613234c05d70f5b DirectoryStorage should be able to remember inexistent files (fixing #196841 - remote FS doesn't work if any part of path to file is r/o) diff -r ca82aebf8161 -r ca06d70d6631 dlight.remote.impl/src/org/netbeans/modules/remote/impl/fs/DirectoryStorage.java --- a/dlight.remote.impl/src/org/netbeans/modules/remote/impl/fs/DirectoryStorage.java Mon Mar 28 09:32:17 2011 +0400 +++ b/dlight.remote.impl/src/org/netbeans/modules/remote/impl/fs/DirectoryStorage.java Mon Mar 28 11:05:39 2011 +0400 @@ -51,8 +51,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; /** * Keeps information about all files that reside in the directory @@ -61,8 +63,10 @@ public final class DirectoryStorage { private final Map entries; + /** known inexistent files in the case of r/o directory - see #196841 - remote FS doesn't work if any part of path to file does not have read permission */ + private final Set dummies = new HashSet(); private final File cacheFile; - private static final int VERSION = RemoteDirectory.getLsViaSftp() ? 3 : 2; + private static final int VERSION = RemoteDirectory.getLsViaSftp() ? 4 : 3; /* Incompatible version to discard */ private static final int ODD_VERSION = RemoteDirectory.getLsViaSftp() ? 3 : 2; @@ -72,11 +76,18 @@ } public DirectoryStorage(File file, Collection newEntries) { + this(file, newEntries, null); + } + + public DirectoryStorage(File file, Collection newEntries, Collection newDummies) { this.cacheFile = file; this.entries = new HashMap(); for (DirEntry entry : newEntries) { entries.put(entry.getName(), entry); } + if (newDummies != null) { + dummies.addAll(newDummies); + } } /** @@ -114,6 +125,25 @@ throw new FormatException("Discarding old directory cache file version " + version + //NNOI18N ' ' + cacheFile.getAbsolutePath(), true); //NOI18N } + line = br.readLine(); + prefix = "dummies="; // NOI18N + if (line == null || ! line.startsWith(prefix)) { + throw new FormatException("Wrong file format " + cacheFile.getAbsolutePath() + " line " + line, false); //NOI18N) + } + int dummiesCount; + try { + dummiesCount = Integer.parseInt(line.substring(prefix.length())); + } catch (NumberFormatException nfe) { + throw new FormatException("wrong dummies count format " + cacheFile.getAbsolutePath(), nfe); // NOI18N + } + for (int i = 0; i < dummiesCount; i++) { + line = br.readLine(); + if (line == null) { + throw new FormatException("premature end of file " + cacheFile.getAbsolutePath(), false); // NOI18N + } else { + dummies.add(line); + } + } while ((line = br.readLine()) != null) { if (line.length() == 0) { continue; // just in case, ignore empty lines @@ -138,12 +168,23 @@ } } + public boolean isKnown(String fileName) { + synchronized (this) { + return entries.containsKey(fileName) || dummies.contains(fileName); + } + } + public void store() throws IOException { BufferedWriter wr = null; synchronized (this) { try { wr = new BufferedWriter(new FileWriter(cacheFile)); wr.write("VERSION=" + VERSION + "\n"); //NOI18N + wr.write("dummies=" + dummies.size() + '\n'); //NOI18N + for (String dummy: dummies) { + wr.write(dummy); + wr.write('\n'); + } for (DirEntry entry : entries.values()) { wr.write(entry.toExternalForm()); wr.write('\n'); @@ -187,6 +228,12 @@ entries.put(entry.getName(), entry); } } + + /*package*/ void testAddDummy(String dummy) { + synchronized (this) { + dummies.add(dummy); + } + } @Override public String toString() { diff -r ca82aebf8161 -r ca06d70d6631 dlight.remote.impl/test/unit/src/org/netbeans/modules/remote/impl/fs/DirectoryStorageLsTestCase.java --- a/dlight.remote.impl/test/unit/src/org/netbeans/modules/remote/impl/fs/DirectoryStorageLsTestCase.java Mon Mar 28 09:32:17 2011 +0400 +++ b/dlight.remote.impl/test/unit/src/org/netbeans/modules/remote/impl/fs/DirectoryStorageLsTestCase.java Mon Mar 28 11:05:39 2011 +0400 @@ -85,6 +85,8 @@ final String link = null; entry1 = new DirEntryLs(name, cacheName, access, user, group, size, timestamp, link); ds1.testAddEntry(entry1); + String dummy = "inexistent_file"; + ds1.testAddDummy(dummy); ds1.store(); DirectoryStorage ds2 = new DirectoryStorage(file); ds2.load(); @@ -98,6 +100,9 @@ assertEquals("Size", size, entry2.getSize()); assertEquals("Timestamp", entry1.getLastModified(), entry2.getLastModified()); assertEquals("Link", link, entry2.getLinkTarget()); + assertTrue(ds2.isKnown(dummy)); + assertFalse(ds2.isKnown("abrakadabra")); + assertTrue(ds2.isKnown(entry2.getName())); } finally { file.delete(); } diff -r ca82aebf8161 -r ca06d70d6631 dlight.remote.impl/test/unit/src/org/netbeans/modules/remote/impl/fs/DirectoryStorageSftpTestCase.java --- a/dlight.remote.impl/test/unit/src/org/netbeans/modules/remote/impl/fs/DirectoryStorageSftpTestCase.java Mon Mar 28 09:32:17 2011 +0400 +++ b/dlight.remote.impl/test/unit/src/org/netbeans/modules/remote/impl/fs/DirectoryStorageSftpTestCase.java Mon Mar 28 11:05:39 2011 +0400 @@ -91,19 +91,22 @@ final String cacheName = "name.cache"; DirEntry entry1 = new DirEntrySftp(statInfo, cacheName); ds1.testAddEntry(entry1); + String dummy = "inexistent_file"; + ds1.testAddDummy(dummy); ds1.store(); DirectoryStorage ds2 = new DirectoryStorage(file); ds2.load(); DirEntry entry2 = ds2.getEntry(entry1.getName()); assertNotNull("No entry restored for " + entry1.getName(), entry2); - assertEquals("Name", entry1.getName(), entry2.getName()); assertEquals("Cache", entry1.getCache(), entry2.getCache()); assertEquals("Access", entry1.getAccessAsString(), entry2.getAccessAsString()); assertEquals("Size", entry1.getSize(), entry2.getSize()); assertTrue("Timestamps differ", entry1.isSameLastModified(entry2)); assertEquals("Link", entry1.getLinkTarget(), entry2.getLinkTarget()); - + assertTrue(ds2.isKnown(dummy)); + assertFalse(ds2.isKnown("abrakadabra")); + assertTrue(ds2.isKnown(entry2.getName())); } finally { file.delete(); }