diff --git a/components/net/sf/briar/plugins/file/PollingRemovableDriveMonitor.java b/components/net/sf/briar/plugins/file/PollingRemovableDriveMonitor.java index 689ce99dd71b1f14ce404a39b827bc6712e5255e..73b86420a823f0089853125d6c9f6e9f57b5e737 100644 --- a/components/net/sf/briar/plugins/file/PollingRemovableDriveMonitor.java +++ b/components/net/sf/briar/plugins/file/PollingRemovableDriveMonitor.java @@ -12,7 +12,7 @@ import net.sf.briar.api.plugins.PluginExecutor; class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable { private static final Logger LOG = - Logger.getLogger(PollingRemovableDriveMonitor.class.getName()); + Logger.getLogger(PollingRemovableDriveMonitor.class.getName()); private final Executor pluginExecutor; private final RemovableDriveFinder finder; @@ -21,7 +21,6 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable { private volatile boolean running = false; private volatile Callback callback = null; - private volatile IOException exception = null; public PollingRemovableDriveMonitor(@PluginExecutor Executor pluginExecutor, RemovableDriveFinder finder, long pollingInterval) { @@ -34,7 +33,6 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable { synchronized(this) { assert !running; assert this.callback == null; - assert exception == null; running = true; this.callback = callback; } @@ -42,19 +40,15 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable { } public void stop() throws IOException { - IOException e; synchronized(this) { assert running; assert callback != null; running = false; callback = null; - e = exception; - exception = null; } synchronized(pollingLock) { pollingLock.notifyAll(); } - if(e != null) throw e; } public void run() { @@ -76,7 +70,7 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable { LOG.info("Interrupted while waiting to poll"); Thread.currentThread().interrupt(); } catch(IOException e) { - exception = e; + callback.exceptionThrown(e); } } } diff --git a/components/net/sf/briar/plugins/file/RemovableDriveMonitor.java b/components/net/sf/briar/plugins/file/RemovableDriveMonitor.java index caa223fc7a7f5a8c4962c323950089894449ff28..9baa030d342435a3a129fb0dad90c63bef1a641e 100644 --- a/components/net/sf/briar/plugins/file/RemovableDriveMonitor.java +++ b/components/net/sf/briar/plugins/file/RemovableDriveMonitor.java @@ -12,5 +12,7 @@ interface RemovableDriveMonitor { interface Callback { void driveInserted(File root); + + void exceptionThrown(IOException e); } } diff --git a/components/net/sf/briar/plugins/file/RemovableDrivePlugin.java b/components/net/sf/briar/plugins/file/RemovableDrivePlugin.java index ab8817fc4063bdf5483df7de4155819b0d7d2900..0fd61460f754a4c5f4ad486997cb74cf2bd6790d 100644 --- a/components/net/sf/briar/plugins/file/RemovableDrivePlugin.java +++ b/components/net/sf/briar/plugins/file/RemovableDrivePlugin.java @@ -123,4 +123,8 @@ implements RemovableDriveMonitor.Callback { for(File f : files) if(f.isFile()) createReaderFromFile(f); } } + + public void exceptionThrown(IOException e) { + if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString()); + } } diff --git a/test/net/sf/briar/plugins/file/PollingRemovableDriveMonitorTest.java b/test/net/sf/briar/plugins/file/PollingRemovableDriveMonitorTest.java index cc9e4f5dda14e65cbf525ef4c132740ef9099cf9..6d9230bffd335de93e923787667a5a127f0accab 100644 --- a/test/net/sf/briar/plugins/file/PollingRemovableDriveMonitorTest.java +++ b/test/net/sf/briar/plugins/file/PollingRemovableDriveMonitorTest.java @@ -3,90 +3,92 @@ package net.sf.briar.plugins.file; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import net.sf.briar.BriarTestCase; import net.sf.briar.plugins.file.RemovableDriveMonitor.Callback; -import org.jmock.Expectations; -import org.jmock.Mockery; import org.junit.Test; public class PollingRemovableDriveMonitorTest extends BriarTestCase { @Test public void testOneCallbackPerFile() throws Exception { + // Create a finder that returns no files the first time, then two files final File file1 = new File("foo"); final File file2 = new File("bar"); - // Create a finder that returns no files the first time, then two files - final List<File> noDrives = Collections.emptyList(); - final List<File> twoDrives = new ArrayList<File>(); - twoDrives.add(file1); - twoDrives.add(file2); - Mockery context = new Mockery(); - final RemovableDriveFinder finder = - context.mock(RemovableDriveFinder.class); - context.checking(new Expectations() {{ - oneOf(finder).findRemovableDrives(); - will(returnValue(noDrives)); - oneOf(finder).findRemovableDrives(); - will(returnValue(twoDrives)); - }}); - // Create a callback that will wait for two files before stopping - final List<File> detected = new ArrayList<File>(); + final RemovableDriveFinder finder = new RemovableDriveFinder() { + + private AtomicBoolean firstCall = new AtomicBoolean(true); + + public Collection<File> findRemovableDrives() throws IOException { + if(firstCall.getAndSet(false)) return Collections.emptyList(); + else return Arrays.asList(new File[] {file1, file2}); + } + }; + // Create a callback that waits for two files final CountDownLatch latch = new CountDownLatch(2); - final Callback callback = new Callback() { + final List<File> detected = new ArrayList<File>(); + Callback callback = new Callback() { + public void driveInserted(File f) { detected.add(f); latch.countDown(); } + + public void exceptionThrown(IOException e) { + fail(); + } }; // Create the monitor and start it final RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor( - Executors.newCachedThreadPool(), finder, 10); + Executors.newCachedThreadPool(), finder, 1); monitor.start(callback); // Wait for the monitor to detect the files - assertTrue(latch.await(5, TimeUnit.SECONDS)); + assertTrue(latch.await(10, TimeUnit.SECONDS)); monitor.stop(); // Check that both files were detected assertEquals(2, detected.size()); assertTrue(detected.contains(file1)); assertTrue(detected.contains(file2)); - // Check that the finder was polled twice - context.assertIsSatisfied(); } @Test - public void testExceptionRethrownWhenStopping() throws Exception { - final List<File> noDrives = Collections.emptyList(); + public void testExceptionCallback() throws Exception { // Create a finder that throws an exception the second time it's polled - Mockery context = new Mockery(); - final RemovableDriveFinder finder = - context.mock(RemovableDriveFinder.class); - context.checking(new Expectations() {{ - oneOf(finder).findRemovableDrives(); - will(returnValue(noDrives)); - oneOf(finder).findRemovableDrives(); - will(throwException(new IOException())); - }}); - // Create the monitor, start it, and give it some time to run - final RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor( - Executors.newCachedThreadPool(), finder, 10); - monitor.start(new Callback() { + final RemovableDriveFinder finder = new RemovableDriveFinder() { + + private AtomicBoolean firstCall = new AtomicBoolean(true); + + public Collection<File> findRemovableDrives() throws IOException { + if(firstCall.getAndSet(false)) return Collections.emptyList(); + else throw new IOException(); + } + }; + // Create a callback that waits for an exception + final CountDownLatch latch = new CountDownLatch(1); + Callback callback = new Callback() { + public void driveInserted(File root) { fail(); } - }); - Thread.sleep(100); - // The monitor should rethrow the exception when it stops - try { - monitor.stop(); - fail(); - } catch(IOException expected) {} - context.assertIsSatisfied(); + + public void exceptionThrown(IOException e) { + latch.countDown(); + } + }; + // Create the monitor and start it + final RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor( + Executors.newCachedThreadPool(), finder, 1); + monitor.start(callback); + assertTrue(latch.await(10, TimeUnit.SECONDS)); + monitor.stop(); } } diff --git a/test/net/sf/briar/plugins/file/UnixRemovableDriveMonitorTest.java b/test/net/sf/briar/plugins/file/UnixRemovableDriveMonitorTest.java index ae3393a54824d04f4f70692133e3daf5e0a197cc..4e7af6079a29cd6bc4b81e0f5bcbeeaffb2f2130 100644 --- a/test/net/sf/briar/plugins/file/UnixRemovableDriveMonitorTest.java +++ b/test/net/sf/briar/plugins/file/UnixRemovableDriveMonitorTest.java @@ -1,6 +1,7 @@ package net.sf.briar.plugins.file; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -33,9 +34,14 @@ public class UnixRemovableDriveMonitorTest extends BriarTestCase { File doesNotExist = new File(testDir, "doesNotExist"); RemovableDriveMonitor monitor = createMonitor(doesNotExist); monitor.start(new Callback() { + public void driveInserted(File root) { fail(); } + + public void exceptionThrown(IOException e) { + fail(); + } }); monitor.stop(); } @@ -50,10 +56,15 @@ public class UnixRemovableDriveMonitorTest extends BriarTestCase { final List<File> detected = new ArrayList<File>(); final CountDownLatch latch = new CountDownLatch(2); final Callback callback = new Callback() { + public void driveInserted(File f) { detected.add(f); latch.countDown(); } + + public void exceptionThrown(IOException e) { + fail(); + } }; // Create the monitor and start it RemovableDriveMonitor monitor = createMonitor(testDir);