Index: lucene/contrib/misc/src/test/org/apache/lucene/store/TestNRTCachingDirectory.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/store/TestNRTCachingDirectory.java	(revision 1159285)
+++ lucene/contrib/misc/src/test/org/apache/lucene/store/TestNRTCachingDirectory.java	(working copy)
@@ -18,7 +18,9 @@
  */
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import org.apache.lucene.analysis.Analyzer;
@@ -117,4 +119,68 @@
     assertEquals(0, dir.listAll().length);
     dir.close();
   }
+  
+  // LUCENE-3382 -- make sure we get exception if the directory really does not exist.
+  public void testNoDir() throws Throwable {
+    Directory dir = new NRTCachingDirectory(newFSDirectory(_TestUtil.getTempDir("doesnotexist")), 2.0, 25.0);
+    try {
+      IndexReader.open(dir, true);
+      fail("did not hit expected exception");
+    } catch (NoSuchDirectoryException nsde) {
+      // expected
+    }
+    dir.close();
+  }
+  
+  // LUCENE-3382 test that we can add a file, and then when we call list() we get it back
+  public void testDirectoryFilter() throws IOException {
+    Directory dir = new NRTCachingDirectory(newFSDirectory(_TestUtil.getTempDir("foo")), 2.0, 25.0);
+    String name = "file";
+    try {
+      dir.createOutput(name, newIOContext(random)).close();
+      assertTrue(dir.fileExists(name));
+      assertTrue(Arrays.asList(dir.listAll()).contains(name));
+    } finally {
+      dir.close();
+    }
+  }
+  
+  // LUCENE-3382 test that delegate compound files correctly.
+  public void testCompoundFileAppendTwice() throws IOException {
+    Directory newDir = new NRTCachingDirectory(newDirectory(), 2.0, 25.0);
+    CompoundFileDirectory csw = newDir.createCompoundOutput("d.cfs", newIOContext(random));
+    createSequenceFile(newDir, "d1", (byte) 0, 15);
+    IndexOutput out = csw.createOutput("d.xyz", newIOContext(random));
+    out.writeInt(0);
+    try {
+      newDir.copy(csw, "d1", "d1", newIOContext(random));
+      fail("file does already exist");
+    } catch (IOException e) {
+      //
+    }
+    out.close();
+    assertEquals(1, csw.listAll().length);
+    assertEquals("d.xyz", csw.listAll()[0]);
+   
+    csw.close();
+
+    CompoundFileDirectory cfr = newDir.openCompoundInput("d.cfs", newIOContext(random));
+    assertEquals(1, cfr.listAll().length);
+    assertEquals("d.xyz", cfr.listAll()[0]);
+    cfr.close();
+    newDir.close();
+  }
+  
+  /** Creates a file of the specified size with sequential data. The first
+   *  byte is written as the start byte provided. All subsequent bytes are
+   *  computed as start + offset where offset is the number of the byte.
+   */
+  private void createSequenceFile(Directory dir, String name, byte start, int size) throws IOException {
+      IndexOutput os = dir.createOutput(name, newIOContext(random));
+      for (int i=0; i < size; i++) {
+          os.writeByte(start);
+          start ++;
+      }
+      os.close();
+  }
 }
Index: lucene/contrib/misc/src/java/org/apache/lucene/store/NRTCachingDirectory.java
===================================================================
--- lucene/contrib/misc/src/java/org/apache/lucene/store/NRTCachingDirectory.java	(revision 1159285)
+++ lucene/contrib/misc/src/java/org/apache/lucene/store/NRTCachingDirectory.java	(working copy)
@@ -120,11 +120,23 @@
     for(String f : cache.listAll()) {
       files.add(f);
     }
-    for(String f : delegate.listAll()) {
-      // Cannot do this -- if lucene calls createOutput but
-      // file already exists then this falsely trips:
-      //assert !files.contains(f): "file \"" + f + "\" is in both dirs";
-      files.add(f);
+    // LUCENE-1468: our NRTCachingDirectory will actually exist (RAMDir!),
+    // but if the underlying delegate is an FSDir and mkdirs() has not
+    // yet been called, because so far everything is a cached write,
+    // in this case, we don't want to throw a NoSuchDirectoryException
+    try {
+      for(String f : delegate.listAll()) {
+        // Cannot do this -- if lucene calls createOutput but
+        // file already exists then this falsely trips:
+        //assert !files.contains(f): "file \"" + f + "\" is in both dirs";
+        files.add(f);
+      }
+    } catch (NoSuchDirectoryException ex) {
+      // however, if there are no cached files, then the directory truly
+      // does not "exist"
+      if (files.isEmpty()) {
+        throw ex;
+      }
     }
     return files.toArray(new String[files.size()]);
   }
@@ -217,25 +229,15 @@
   }
 
   @Override
-  public synchronized CompoundFileDirectory openCompoundInput(String name, IOContext context) throws IOException {
-    if (cache.fileExists(name)) {
-      return cache.openCompoundInput(name, context);
-    } else {
-      return delegate.openCompoundInput(name, context);
-    }
+  public final CompoundFileDirectory openCompoundInput(String name, IOContext context) throws IOException {
+    return super.openCompoundInput(name, context);
   }
   
   @Override
-  public synchronized CompoundFileDirectory createCompoundOutput(String name, IOContext context)
-      throws IOException {
-    if (cache.fileExists(name)) {
-      throw new IOException("File " + name + "already exists");
-    } else {
-      return delegate.createCompoundOutput(name, context);
-    }
+  public final CompoundFileDirectory createCompoundOutput(String name, IOContext context) throws IOException {
+    return super.createCompoundOutput(name, context);
   }
 
-
   /** Close this directory, which flushes any cached files
    *  to the delegate and then closes the delegate. */
   @Override
