diff --git a/api/net/sf/briar/api/plugins/PluginManager.java b/api/net/sf/briar/api/plugins/PluginManager.java index 2fae4b17c8789b8d315d2d67fbfc8f495ae4608a..b2dbd44ae00ccffd22dee53f7f383354f63f0422 100644 --- a/api/net/sf/briar/api/plugins/PluginManager.java +++ b/api/net/sf/briar/api/plugins/PluginManager.java @@ -6,10 +6,10 @@ public interface PluginManager { * Starts the plugins and returns the number of plugins successfully * started. */ - int startPlugins(); + int start(); /** * Stops the plugins and returns the number of plugins successfully stopped. */ - int stopPlugins(); + int stop(); } diff --git a/components/net/sf/briar/plugins/PluginManagerImpl.java b/components/net/sf/briar/plugins/PluginManagerImpl.java index a88c8b563c7d5d6c47a13cb4f4a8bb8ccdd340fb..5d16299efbed81f19e73710628f1d70e1d331b02 100644 --- a/components/net/sf/briar/plugins/PluginManagerImpl.java +++ b/components/net/sf/briar/plugins/PluginManagerImpl.java @@ -76,7 +76,7 @@ class PluginManagerImpl implements PluginManager { return batchPlugins.size() + streamPlugins.size(); } - public synchronized int startPlugins() { + public synchronized int start() { Set<TransportId> ids = new HashSet<TransportId>(); // Instantiate and start the batch plugins for(String s : BATCH_FACTORIES) { @@ -162,12 +162,12 @@ class PluginManagerImpl implements PluginManager { List<Plugin> plugins = new ArrayList<Plugin>(); plugins.addAll(batchPlugins); plugins.addAll(streamPlugins); - poller.startPolling(Collections.unmodifiableList(plugins)); + poller.start(Collections.unmodifiableList(plugins)); // Return the number of plugins successfully started return batchPlugins.size() + streamPlugins.size(); } - public synchronized int stopPlugins() { + public synchronized int stop() { int stopped = 0; // Stop the batch plugins for(BatchPlugin plugin : batchPlugins) { @@ -189,6 +189,10 @@ class PluginManagerImpl implements PluginManager { } } streamPlugins.clear(); + // Stop the poller + poller.stop(); + // Shut down the executor service + pluginExecutor.shutdown(); // Return the number of plugins successfully stopped return stopped; } diff --git a/components/net/sf/briar/plugins/Poller.java b/components/net/sf/briar/plugins/Poller.java index 0c349722aa5256ff05585d93670cd7ced444b74a..d5eb381ba6b791fce48a92c2508db3a051367588 100644 --- a/components/net/sf/briar/plugins/Poller.java +++ b/components/net/sf/briar/plugins/Poller.java @@ -7,8 +7,8 @@ import net.sf.briar.api.plugins.Plugin; interface Poller { /** Starts a new thread to poll the given collection of plugins. */ - void startPolling(Collection<Plugin> plugins); + void start(Collection<Plugin> plugins); /** Tells the poller thread to exit. */ - void stopPolling(); + void stop(); } diff --git a/components/net/sf/briar/plugins/PollerImpl.java b/components/net/sf/briar/plugins/PollerImpl.java index 3245c08a693bacf84b43e05b83dd1c28a3dcd1bf..b1e3d6e68df5956e1292cee61a73d489b171767b 100644 --- a/components/net/sf/briar/plugins/PollerImpl.java +++ b/components/net/sf/briar/plugins/PollerImpl.java @@ -26,7 +26,7 @@ class PollerImpl implements Poller, Runnable { pollTimes = new TreeSet<PollTime>(); } - public synchronized void startPolling(Collection<Plugin> plugins) { + public synchronized void start(Collection<Plugin> plugins) { for(Plugin plugin : plugins) schedule(plugin); new Thread(this).start(); } @@ -39,7 +39,7 @@ class PollerImpl implements Poller, Runnable { } } - public synchronized void stopPolling() { + public synchronized void stop() { pollTimes.clear(); notifyAll(); } diff --git a/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java b/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java index 7884ead6c5658f3175db0dea1f1bd3d22ee874a7..536de88124b1d93f49d071a178415bc07ab5e993 100644 --- a/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java +++ b/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java @@ -1,6 +1,7 @@ package net.sf.briar.plugins.bluetooth; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -8,6 +9,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Random; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; @@ -43,6 +45,7 @@ class BluetoothPlugin implements StreamPlugin { private final StreamPluginCallback callback; private final long pollingInterval; private final Object discoveryLock = new Object(); + private final Collection<ScheduledFuture<?>> socketClosers; // Locking: this private boolean running = false; // Locking: this private LocalDevice localDevice = null; // Locking: this @@ -53,6 +56,7 @@ class BluetoothPlugin implements StreamPlugin { this.pluginExecutor = pluginExecutor; this.callback = callback; this.pollingInterval = pollingInterval; + socketClosers = new ArrayList<ScheduledFuture<?>>(); } public TransportId getId() { @@ -167,6 +171,7 @@ class BluetoothPlugin implements StreamPlugin { public synchronized void stop() throws IOException { running = false; + for(ScheduledFuture<?> close : socketClosers) close.cancel(false); localDevice = null; if(socket != null) { socket.close(); @@ -377,11 +382,15 @@ class BluetoothPlugin implements StreamPlugin { return; } // Close the socket when the invitation times out - pluginExecutor.schedule(new Runnable() { + Runnable close = new Runnable() { public void run() { tryToClose(scn); } - }, c.getTimeout(), TimeUnit.MILLISECONDS); + }; + synchronized(this) { + socketClosers.add(pluginExecutor.schedule(close, c.getTimeout(), + TimeUnit.MILLISECONDS)); + } try { StreamConnection s = scn.acceptAndOpen(); c.addConnection(s); diff --git a/test/net/sf/briar/plugins/PluginManagerImplTest.java b/test/net/sf/briar/plugins/PluginManagerImplTest.java index 48f47eb256d590e3b63b6ab6079ffa3cc5b25c31..37c50e3966592eaecc046c358da53a8afa718467 100644 --- a/test/net/sf/briar/plugins/PluginManagerImplTest.java +++ b/test/net/sf/briar/plugins/PluginManagerImplTest.java @@ -30,7 +30,7 @@ public class PluginManagerImplTest extends BriarTestCase { final UiCallback uiCallback = context.mock(UiCallback.class); final AtomicInteger index = new AtomicInteger(0); context.checking(new Expectations() {{ - oneOf(poller).startPolling(with(any(Collection.class))); + oneOf(poller).start(with(any(Collection.class))); allowing(db).getLocalIndex(with(any(TransportId.class))); will(returnValue(null)); allowing(db).addTransport(with(any(TransportId.class))); @@ -41,17 +41,18 @@ public class PluginManagerImplTest extends BriarTestCase { will(returnValue(new TransportProperties())); allowing(db).setLocalProperties(with(any(TransportId.class)), with(any(TransportProperties.class))); - oneOf(poller).stopPolling(); + oneOf(poller).stop(); }}); ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); PluginManagerImpl p = new PluginManagerImpl(executor, db, poller, dispatcher, uiCallback); // We expect either 2 or 3 plugins to be started, depending on whether // the test machine has a Bluetooth device - int started = p.startPlugins(); - int stopped = p.stopPlugins(); + int started = p.start(); + int stopped = p.stop(); assertEquals(started, stopped); assertTrue(started >= 2); assertTrue(started <= 3); + context.assertIsSatisfied(); } }