Use Guice rather than reflection to load plugins.

This allows different plugins to have different dependencies without
cluttering the plugin factory API.
This commit is contained in:
akwizgran
2012-12-15 01:16:48 +00:00
parent 8bc27528a6
commit f5628e5581
14 changed files with 209 additions and 158 deletions

View File

@@ -20,24 +20,24 @@ import net.sf.briar.api.TransportProperties;
import net.sf.briar.api.android.AndroidExecutor;
import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.plugins.Plugin;
import net.sf.briar.api.plugins.PluginCallback;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.PluginManager;
import net.sf.briar.api.plugins.duplex.DuplexPlugin;
import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
import net.sf.briar.api.plugins.duplex.DuplexPluginConfig;
import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
import net.sf.briar.api.plugins.simplex.SimplexPlugin;
import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
import net.sf.briar.api.plugins.simplex.SimplexPluginConfig;
import net.sf.briar.api.plugins.simplex.SimplexPluginFactory;
import net.sf.briar.api.plugins.simplex.SimplexTransportReader;
import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.transport.ConnectionDispatcher;
import net.sf.briar.api.ui.UiCallback;
import net.sf.briar.util.OsUtils;
import android.content.Context;
import com.google.inject.Inject;
@@ -47,30 +47,10 @@ class PluginManagerImpl implements PluginManager {
private static final Logger LOG =
Logger.getLogger(PluginManagerImpl.class.getName());
private static final String[] ANDROID_SIMPLEX_FACTORIES = new String[0];
private static final String[] ANDROID_DUPLEX_FACTORIES = new String[] {
"net.sf.briar.plugins.droidtooth.DroidtoothPluginFactory",
"net.sf.briar.plugins.tcp.LanTcpPluginFactory",
"net.sf.briar.plugins.tcp.WanTcpPluginFactory",
"net.sf.briar.plugins.tor.TorPluginFactory"
};
private static final String[] J2SE_SIMPLEX_FACTORIES = new String[] {
"net.sf.briar.plugins.file.RemovableDrivePluginFactory"
};
private static final String[] J2SE_DUPLEX_FACTORIES = new String[] {
"net.sf.briar.plugins.bluetooth.BluetoothPluginFactory",
"net.sf.briar.plugins.modem.ModemPluginFactory",
"net.sf.briar.plugins.tcp.LanTcpPluginFactory",
"net.sf.briar.plugins.tcp.WanTcpPluginFactory",
"net.sf.briar.plugins.tor.TorPluginFactory"
};
private final ExecutorService pluginExecutor;
private final AndroidExecutor androidExecutor;
private final ShutdownManager shutdownManager;
private final SimplexPluginConfig simplexPluginConfig;
private final DuplexPluginConfig duplexPluginConfig;
private final DatabaseComponent db;
private final Poller poller;
private final ConnectionDispatcher dispatcher;
@@ -80,12 +60,15 @@ class PluginManagerImpl implements PluginManager {
@Inject
PluginManagerImpl(@PluginExecutor ExecutorService pluginExecutor,
AndroidExecutor androidExecutor, ShutdownManager shutdownManager,
DatabaseComponent db, Poller poller,
ConnectionDispatcher dispatcher, UiCallback uiCallback) {
AndroidExecutor androidExecutor,
SimplexPluginConfig simplexPluginConfig,
DuplexPluginConfig duplexPluginConfig, DatabaseComponent db,
Poller poller, ConnectionDispatcher dispatcher,
UiCallback uiCallback) {
this.pluginExecutor = pluginExecutor;
this.androidExecutor = androidExecutor;
this.shutdownManager = shutdownManager;
this.simplexPluginConfig = simplexPluginConfig;
this.duplexPluginConfig = duplexPluginConfig;
this.db = db;
this.poller = poller;
this.dispatcher = dispatcher;
@@ -98,27 +81,23 @@ class PluginManagerImpl implements PluginManager {
Set<TransportId> ids = new HashSet<TransportId>();
// Instantiate and start the simplex plugins
if(LOG.isLoggable(INFO)) LOG.info("Starting simplex plugins");
for(String s : getSimplexPluginFactoryNames()) {
for(SimplexPluginFactory factory : simplexPluginConfig.getFactories()) {
TransportId id = factory.getId();
if(!ids.add(id)) {
if(LOG.isLoggable(WARNING))
LOG.warning("Duplicate transport ID: " + id);
continue;
}
SimplexCallback callback = new SimplexCallback(id);
SimplexPlugin plugin = factory.createPlugin(callback);
if(plugin == null) {
if(LOG.isLoggable(INFO)) {
LOG.info(factory.getClass().getSimpleName()
+ " did not create a plugin");
}
continue;
}
try {
Class<?> c = Class.forName(s);
SimplexPluginFactory factory =
(SimplexPluginFactory) c.newInstance();
TransportId id = factory.getId();
if(!ids.add(id)) {
if(LOG.isLoggable(WARNING))
LOG.warning("Duplicate transport ID: " + id);
continue;
}
SimplexCallback callback = new SimplexCallback(id);
SimplexPlugin plugin = factory.createPlugin(pluginExecutor,
androidExecutor, appContext, shutdownManager, callback);
if(plugin == null) {
if(LOG.isLoggable(INFO)) {
LOG.info(factory.getClass().getSimpleName()
+ " did not create a plugin");
}
continue;
}
if(plugin.start()) {
simplexPlugins.add(plugin);
} else {
@@ -126,37 +105,29 @@ class PluginManagerImpl implements PluginManager {
LOG.info(plugin.getClass().getSimpleName()
+ " did not start");
}
} catch(ClassCastException e) {
} catch(IOException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
continue;
} catch(Exception e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
continue;
}
}
// Instantiate and start the duplex plugins
if(LOG.isLoggable(INFO)) LOG.info("Starting duplex plugins");
for(String s : getDuplexPluginFactoryNames()) {
for(DuplexPluginFactory factory : duplexPluginConfig.getFactories()) {
TransportId id = factory.getId();
if(!ids.add(id)) {
if(LOG.isLoggable(WARNING))
LOG.warning("Duplicate transport ID: " + id);
continue;
}
DuplexCallback callback = new DuplexCallback(id);
DuplexPlugin plugin = factory.createPlugin(callback);
if(plugin == null) {
if(LOG.isLoggable(INFO)) {
LOG.info(factory.getClass().getSimpleName()
+ " did not create a plugin");
}
continue;
}
try {
Class<?> c = Class.forName(s);
DuplexPluginFactory factory =
(DuplexPluginFactory) c.newInstance();
TransportId id = factory.getId();
if(!ids.add(id)) {
if(LOG.isLoggable(WARNING))
LOG.warning("Duplicate transport ID: " + id);
continue;
}
DuplexCallback callback = new DuplexCallback(id);
DuplexPlugin plugin = factory.createPlugin(pluginExecutor,
androidExecutor, appContext, shutdownManager, callback);
if(plugin == null) {
if(LOG.isLoggable(INFO)) {
LOG.info(factory.getClass().getSimpleName()
+ " did not create a plugin");
}
continue;
}
if(plugin.start()) {
duplexPlugins.add(plugin);
} else {
@@ -164,12 +135,8 @@ class PluginManagerImpl implements PluginManager {
LOG.info(plugin.getClass().getSimpleName()
+ " did not start");
}
} catch(ClassCastException e) {
} catch(IOException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
continue;
} catch(Exception e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
continue;
}
}
// Start the poller
@@ -182,16 +149,6 @@ class PluginManagerImpl implements PluginManager {
return simplexPlugins.size() + duplexPlugins.size();
}
private static String[] getSimplexPluginFactoryNames() {
if(OsUtils.isAndroid()) return ANDROID_SIMPLEX_FACTORIES;
return J2SE_SIMPLEX_FACTORIES;
}
private static String[] getDuplexPluginFactoryNames() {
if(OsUtils.isAndroid()) return ANDROID_DUPLEX_FACTORIES;
return J2SE_DUPLEX_FACTORIES;
}
public synchronized int stop() {
int stopped = 0;
// Stop the poller

View File

@@ -1,12 +1,31 @@
package net.sf.briar.plugins;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import net.sf.briar.api.android.AndroidExecutor;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.PluginManager;
import net.sf.briar.api.plugins.duplex.DuplexPluginConfig;
import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
import net.sf.briar.api.plugins.simplex.SimplexPluginConfig;
import net.sf.briar.api.plugins.simplex.SimplexPluginFactory;
import net.sf.briar.plugins.bluetooth.BluetoothPluginFactory;
import net.sf.briar.plugins.droidtooth.DroidtoothPluginFactory;
import net.sf.briar.plugins.file.RemovableDrivePluginFactory;
import net.sf.briar.plugins.modem.ModemPluginFactory;
import net.sf.briar.plugins.tcp.LanTcpPluginFactory;
import net.sf.briar.plugins.tcp.WanTcpPluginFactory;
import net.sf.briar.plugins.tor.TorPluginFactory;
import net.sf.briar.util.OsUtils;
import android.content.Context;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;
public class PluginsModule extends AbstractModule {
@@ -21,4 +40,45 @@ public class PluginsModule extends AbstractModule {
PluginManagerImpl.class).in(Singleton.class);
bind(Poller.class).to(PollerImpl.class);
}
@Provides
SimplexPluginConfig getSimplexPluginConfig(
@PluginExecutor Executor pluginExecutor) {
final Collection<SimplexPluginFactory> factories =
new ArrayList<SimplexPluginFactory>();
if(!OsUtils.isAndroid()) {
// No simplex plugins for Android
} else {
factories.add(new RemovableDrivePluginFactory(pluginExecutor));
}
return new SimplexPluginConfig() {
public Collection<SimplexPluginFactory> getFactories() {
return factories;
}
};
}
@Provides
DuplexPluginConfig getDuplexPluginConfig(
@PluginExecutor Executor pluginExecutor,
AndroidExecutor androidExecutor, Context appContext,
ShutdownManager shutdownManager) {
final Collection<DuplexPluginFactory> factories =
new ArrayList<DuplexPluginFactory>();
if(OsUtils.isAndroid()) {
factories.add(new DroidtoothPluginFactory(pluginExecutor,
androidExecutor, appContext));
} else {
factories.add(new BluetoothPluginFactory(pluginExecutor));
factories.add(new ModemPluginFactory(pluginExecutor));
}
factories.add(new LanTcpPluginFactory(pluginExecutor));
factories.add(new WanTcpPluginFactory(pluginExecutor, shutdownManager));
factories.add(new TorPluginFactory(pluginExecutor));
return new DuplexPluginConfig() {
public Collection<DuplexPluginFactory> getFactories() {
return factories;
}
};
}
}

View File

@@ -2,27 +2,28 @@ package net.sf.briar.plugins.bluetooth;
import java.util.concurrent.Executor;
import net.sf.briar.api.android.AndroidExecutor;
import net.sf.briar.api.clock.SystemClock;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.duplex.DuplexPlugin;
import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
import net.sf.briar.api.protocol.TransportId;
import android.content.Context;
public class BluetoothPluginFactory implements DuplexPluginFactory {
private static final long POLLING_INTERVAL = 3L * 60L * 1000L; // 3 mins
private final Executor pluginExecutor;
public BluetoothPluginFactory(@PluginExecutor Executor pluginExecutor) {
this.pluginExecutor = pluginExecutor;
}
public TransportId getId() {
return BluetoothPlugin.ID;
}
public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
AndroidExecutor androidExecutor, Context appContext,
ShutdownManager shutdownManager, DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
return new BluetoothPlugin(pluginExecutor, new SystemClock(), callback,
POLLING_INTERVAL);
}

View File

@@ -3,7 +3,6 @@ package net.sf.briar.plugins.droidtooth;
import java.util.concurrent.Executor;
import net.sf.briar.api.android.AndroidExecutor;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.duplex.DuplexPlugin;
import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
@@ -15,13 +14,22 @@ public class DroidtoothPluginFactory implements DuplexPluginFactory {
private static final long POLLING_INTERVAL = 3L * 60L * 1000L; // 3 mins
private final Executor pluginExecutor;
private final AndroidExecutor androidExecutor;
private final Context appContext;
public DroidtoothPluginFactory(@PluginExecutor Executor pluginExecutor,
AndroidExecutor androidExecutor, Context appContext) {
this.pluginExecutor = pluginExecutor;
this.androidExecutor = androidExecutor;
this.appContext = appContext;
}
public TransportId getId() {
return DroidtoothPlugin.ID;
}
public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
AndroidExecutor androidExecutor, Context appContext,
ShutdownManager shutdownManager, DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
return new DroidtoothPlugin(pluginExecutor, androidExecutor, appContext,
callback, POLLING_INTERVAL);
}

View File

@@ -2,27 +2,29 @@ package net.sf.briar.plugins.file;
import java.util.concurrent.Executor;
import net.sf.briar.api.android.AndroidExecutor;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.simplex.SimplexPlugin;
import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
import net.sf.briar.api.plugins.simplex.SimplexPluginFactory;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.util.OsUtils;
import android.content.Context;
public class RemovableDrivePluginFactory implements SimplexPluginFactory {
private static final long POLLING_INTERVAL = 10L * 1000L; // 10 seconds
private final Executor pluginExecutor;
public RemovableDrivePluginFactory(
@PluginExecutor Executor pluginExecutor) {
this.pluginExecutor = pluginExecutor;
}
public TransportId getId() {
return RemovableDrivePlugin.ID;
}
public SimplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
AndroidExecutor androidExecutor, Context appContext,
ShutdownManager shutdownManager, SimplexPluginCallback callback) {
public SimplexPlugin createPlugin(SimplexPluginCallback callback) {
RemovableDriveFinder finder;
RemovableDriveMonitor monitor;
if(OsUtils.isLinux()) {

View File

@@ -2,8 +2,6 @@ package net.sf.briar.plugins.modem;
import java.util.concurrent.Executor;
import net.sf.briar.api.android.AndroidExecutor;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.duplex.DuplexPlugin;
import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
@@ -12,19 +10,21 @@ import net.sf.briar.api.protocol.TransportId;
import org.h2.util.StringUtils;
import android.content.Context;
public class ModemPluginFactory implements DuplexPluginFactory {
private static final long POLLING_INTERVAL = 60L * 60L * 1000L; // 1 hour
private final Executor pluginExecutor;
public ModemPluginFactory(@PluginExecutor Executor pluginExecutor) {
this.pluginExecutor = pluginExecutor;
}
public TransportId getId() {
return ModemPlugin.ID;
}
public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
AndroidExecutor androidExecutor, Context appContext,
ShutdownManager shutdownManager, DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
// This plugin is not enabled by default
String enabled = callback.getConfig().get("enabled");
if(StringUtils.isNullOrEmpty(enabled)) return null;

View File

@@ -2,26 +2,27 @@ package net.sf.briar.plugins.tcp;
import java.util.concurrent.Executor;
import net.sf.briar.api.android.AndroidExecutor;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.duplex.DuplexPlugin;
import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
import net.sf.briar.api.protocol.TransportId;
import android.content.Context;
public class LanTcpPluginFactory implements DuplexPluginFactory {
private static final long POLLING_INTERVAL = 60L * 1000L; // 1 minute
private final Executor pluginExecutor;
public LanTcpPluginFactory(@PluginExecutor Executor pluginExecutor) {
this.pluginExecutor = pluginExecutor;
}
public TransportId getId() {
return LanTcpPlugin.ID;
}
public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
AndroidExecutor androidExecutor, Context appContext,
ShutdownManager shutdownManager, DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
return new LanTcpPlugin(pluginExecutor, callback, POLLING_INTERVAL);
}
}

View File

@@ -2,26 +2,31 @@ package net.sf.briar.plugins.tcp;
import java.util.concurrent.Executor;
import net.sf.briar.api.android.AndroidExecutor;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.duplex.DuplexPlugin;
import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
import net.sf.briar.api.protocol.TransportId;
import android.content.Context;
public class WanTcpPluginFactory implements DuplexPluginFactory {
private static final long POLLING_INTERVAL = 5L * 60L * 1000L; // 5 minutes
private final Executor pluginExecutor;
private final ShutdownManager shutdownManager;
public WanTcpPluginFactory(@PluginExecutor Executor pluginExecutor,
ShutdownManager shutdownManager) {
this.pluginExecutor = pluginExecutor;
this.shutdownManager = shutdownManager;
}
public TransportId getId() {
return WanTcpPlugin.ID;
}
public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
AndroidExecutor androidExecutor, Context appContext,
ShutdownManager shutdownManager, DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
return new WanTcpPlugin(pluginExecutor, callback, POLLING_INTERVAL,
new PortMapperImpl(shutdownManager));
}

View File

@@ -2,8 +2,6 @@ package net.sf.briar.plugins.tor;
import java.util.concurrent.Executor;
import net.sf.briar.api.android.AndroidExecutor;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.plugins.PluginExecutor;
import net.sf.briar.api.plugins.duplex.DuplexPlugin;
import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
@@ -12,19 +10,21 @@ import net.sf.briar.api.protocol.TransportId;
import org.h2.util.StringUtils;
import android.content.Context;
public class TorPluginFactory implements DuplexPluginFactory {
private static final long POLLING_INTERVAL = 15L * 60L * 1000L; // 15 mins
private final Executor pluginExecutor;
public TorPluginFactory(@PluginExecutor Executor pluginExecutor) {
this.pluginExecutor = pluginExecutor;
}
public TransportId getId() {
return TorPlugin.ID;
}
public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor,
AndroidExecutor androidExecutor, Context appContext,
ShutdownManager shutdownManager, DuplexPluginCallback callback) {
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
// This plugin is not enabled by default
String enabled = callback.getConfig().get("enabled");
if(StringUtils.isNullOrEmpty(enabled)) return null;