package edu.washington.cs.oneswarm.f2f;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.gudy.azureus2.core3.config.impl.ConfigurationManager;
import edu.washington.cs.oneswarm.ui.gwt.CoreInterface;
public class ExperimentalHarnessManager {
private static ExperimentalHarnessManager inst;
public static final String EXPERIMENTAL_CONFIG_PROPERTY = "oneswarm.experimental.config.file";
private static List<ExperimentInterface> experiments;
private static Logger logger = Logger.getLogger(ExperimentalHarnessManager.class.getName());
private CoreInterface core;
/**
* Get the ExperimentalHarnessManger. The manager will only be provided if
* this instance of oneswarm is running with experimental code enabled.
*
* @return The ExperimentalHarnessManager.
*/
public static ExperimentalHarnessManager get() {
if (inst == null) {
experiments = new ArrayList<ExperimentInterface>();
inst = new ExperimentalHarnessManager();
}
return inst;
}
/**
* Determine if Experimental code should be run. Triggers on whether
* configuration
* contains a "oneswarm.experimental.config.file" property.
*
* @return True if experimental code should be loaded.
*/
public static boolean isEnabled() {
return System.getProperty(EXPERIMENTAL_CONFIG_PROPERTY) != null;
}
/**
* Create a new experimental harness manager. This class is a singleton,
* instances should be accessed through ExperimentalHarnessManager.get().
*/
private ExperimentalHarnessManager() {
// Private constructor. Access via get().
}
/**
* Set the core oneswarm interface, so that experiments are able to
* access oneswarm internals.
*
* @param core
* The Oneswarm Core.
*/
public void setCore(CoreInterface core) {
this.core = core;
}
/**
* Get the core oneswarm interface - meant for use by experiments.
*
* @return The Oneswarm Core.
*/
public CoreInterface getCoreInterface() {
return core;
}
/**
* Start the ExperimentalHarness - Load all experiments, and
* process commands listed in the experimental configuration file.
*/
public void start() {
// Distribute initial commands.
try {
String path = System.getProperty(EXPERIMENTAL_CONFIG_PROPERTY);
if (path != null) {
logger.info("Loading experimental configuration from " + path);
BufferedReader in = new BufferedReader(new FileReader(path));
while (in.ready()) {
String line = in.readLine();
if (line == null) {
break;
}
distribute(line);
}
ConfigurationManager.getInstance().setDirty();
}
} catch (Exception e) {
e.printStackTrace();
logger.warning(e.getMessage());
}
}
/**
* Attempt to execute a command string by distributing it to the first
* experiment which lists the first word of the command in it's list of
* keys.
*
* @param command
* The command to execute.
*/
protected void distribute(String command) {
String[] toks = command.split(" ");
String key = toks[0];
if (key.equals("inject")) {
try {
// Huzzah for reflection.
ExperimentInterface experiment = (ExperimentInterface) Thread.currentThread()
.getContextClassLoader().loadClass(toks[1].trim()).getConstructor()
.newInstance();
logger.info("Added experiments in " + toks[1]);
experiment.load();
experiments.add(experiment);
} catch (Exception e) {
logger.warning("Could not load experiment provider " + toks[1]);
logger.warning("Classpath is " + System.getProperty("java.class.path", null));
e.printStackTrace();
}
return;
}
for (ExperimentInterface ei : experiments) {
for (String offer : ei.getKeys()) {
if (offer.equals(key)) {
logger.fine(key + " is executed by " + ei.getClass().getName());
ei.execute(command);
return;
}
}
}
}
public void enqueue(String[] commands) {
for (String command : commands) {
distribute(command);
}
ConfigurationManager.getInstance().setDirty();
}
}