diff --git a/pom.xml b/pom.xml index 9bf2c6d5319c4ce47d79e13325a52750cc823b3b..1a37142e64dcde75bec6b23cb852f4fcb0089deb 100644 --- a/pom.xml +++ b/pom.xml @@ -51,5 +51,10 @@ <artifactId>akka-remote_2.11</artifactId> <version>2.4.7</version> </dependency> + <dependency> + <groupId>org.reflections</groupId> + <artifactId>reflections</artifactId> + <version>0.9.10</version> + </dependency> </dependencies> </project> \ No newline at end of file diff --git a/src/main/java/fucoin/Main.java b/src/main/java/fucoin/Main.java index f992c440a959554f54202ec4ef9c4a260ea4f599..2b491c8ba39ad8f2c2a13262a961cb2f82377665 100644 --- a/src/main/java/fucoin/Main.java +++ b/src/main/java/fucoin/Main.java @@ -1,31 +1,30 @@ package fucoin; -import akka.actor.ActorRef; import akka.actor.ActorSystem; -import akka.actor.Props; import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; -import fucoin.actions.join.ActionTellSupervisor; +import fucoin.configurations.AbstractConfiguration; import fucoin.setup.NetworkInterfaceReader; -import fucoin.supervisor.SuperVisorImpl; -import fucoin.wallet.WalletImpl; - +import org.reflections.Reflections; +import org.reflections.scanners.ResourcesScanner; +import org.reflections.scanners.SubTypesScanner; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; +import org.reflections.util.FilterBuilder; + +import javax.swing.*; import java.io.File; +import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; +import java.util.Set; public class Main { - private static int numberOfWallets = 2; - private static boolean createGUI = false; - private static ActorSystem cSystem; - private static ActorRef cSuperVisorActor; - - private static List<ActorRef> cActiveActors = new ArrayList<>(); - static { String hostname = NetworkInterfaceReader.readDefaultHostname(); @@ -41,37 +40,45 @@ public class Main { //Init System Actor System cSystem = ActorSystem.create("Core", ConfigFactory.parseString("akka.remote.netty.tcp.hostname=" + hostname).withFallback(config)); - cSuperVisorActor = cSystem.actorOf(SuperVisorImpl.props(), "SuperVisorImpl"); } - public static void main(String[] args) throws InterruptedException { - createWallets(); + public static void main(String[] args) throws InterruptedException, IllegalAccessException, InstantiationException { + List<AbstractConfiguration> configurations = getAbstractConfigurations(); + + AbstractConfiguration[] configs = new AbstractConfiguration[configurations.size()]; + configurations.toArray(configs); + + AbstractConfiguration selectedConfig = (AbstractConfiguration) JOptionPane.showInputDialog(null, "Select a configuration to run", "Configuration Selection", JOptionPane.QUESTION_MESSAGE, null, configs, configurations.get(0)); + if (selectedConfig != null) { + selectedConfig.setSystem(cSystem); + selectedConfig.run(); + } else { + cSystem.terminate(); + } } - private static void createWallets() { - //Init Wallets - for (int i = 0; i < numberOfWallets; i++) { + private static List<AbstractConfiguration> getAbstractConfigurations() throws InstantiationException, IllegalAccessException { + List<ClassLoader> classLoadersList = new LinkedList<>(); + classLoadersList.add(ClasspathHelper.contextClassLoader()); + classLoadersList.add(ClasspathHelper.staticClassLoader()); - String nameOfTheWallet = "Wallet" + String.valueOf(i); - Props props; + Reflections reflections = new Reflections(new ConfigurationBuilder() + .setScanners(new SubTypesScanner(false), new ResourcesScanner()) + .setUrls(ClasspathHelper.forClassLoader(classLoadersList.toArray(new ClassLoader[0]))) + .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("fucoin.configurations")))); - if (i > 0) { - //chain the wallets. wallet2 knows wallet1, wallet3 knows wallet2 and so on. - props = WalletImpl.props(cActiveActors.get(i - 1), nameOfTheWallet, createGUI); - } else { - props = WalletImpl.props(null, nameOfTheWallet, createGUI); - } + Set<Class<? extends Object>> allClasses = + reflections.getSubTypesOf(Object.class); - ActorRef actorRef = cSystem.actorOf(props, nameOfTheWallet); + List<AbstractConfiguration> configurations = new ArrayList<>(); - // first wallet does not have a neighbour, so it can't send a ActionJoin to anybody - // instead we send directly an ActionJoinAnswer with the supervisor reference - if (i == 0) { - //actorRef.tell(new ActionJoinAnswer(cSuperVisorActor), cSuperVisorActor); - actorRef.tell(new ActionTellSupervisor(cSuperVisorActor), cSuperVisorActor); + for (Class<? extends Object> oneClass: allClasses){ + if (!Modifier.isAbstract(oneClass.getModifiers())) { + AbstractConfiguration cfg = (AbstractConfiguration)oneClass.newInstance(); + cfg.setSystem(cSystem); + configurations.add(cfg); } - - cActiveActors.add(actorRef); } + return configurations; } } diff --git a/src/main/java/fucoin/configurations/AbstractConfiguration.java b/src/main/java/fucoin/configurations/AbstractConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..649ef96d1ea5a1ce851bcb919c4947974f044950 --- /dev/null +++ b/src/main/java/fucoin/configurations/AbstractConfiguration.java @@ -0,0 +1,75 @@ +package fucoin.configurations; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.actor.Props; +import fucoin.actions.join.ActionTellSupervisor; +import fucoin.supervisor.SuperVisorImpl; +import fucoin.wallet.WalletImpl; + +import java.util.ArrayList; +import java.util.List; + +/** + * + */ +public abstract class AbstractConfiguration { + + protected ActorSystem cSystem; + protected ActorRef superVisor; + + protected final List<ActorRef> activeActors = new ArrayList<>(); + + public void setSystem(ActorSystem system) { + cSystem = system; + } + + public ActorRef spawnWallet(String name, boolean createGUI) { + Props props; + int numOfWallets = activeActors.size(); + if (numOfWallets == 0) { + props = WalletImpl.props(null, name, createGUI); + } else { + props = WalletImpl.props(activeActors.get(numOfWallets - 1), name, createGUI); + } + + ActorRef actorRef = cSystem.actorOf(props, name); + + activeActors.add(actorRef); + + if (numOfWallets == 0) { + //actorRef.tell(new ActionJoinAnswer(cSuperVisorActor), cSuperVisorActor); + actorRef.tell(new ActionTellSupervisor(superVisor), superVisor); + } + + return actorRef; + } + + public void spawnWallets(int n, boolean createGUI) { + for (int i = 0; i < n; i++) { + String nameOfTheWallet = "Wallet" + String.valueOf(activeActors.size()); + spawnWallet(nameOfTheWallet, createGUI); + } + } + + public ActorRef initSupervisor() { + superVisor = cSystem.actorOf(SuperVisorImpl.props(), "SuperVisorImpl"); + + // Don't ask. + try { + Thread.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return superVisor; + } + + public abstract void run(); + + public abstract String getName(); + + @Override + public String toString() { + return getName(); + } +} diff --git a/src/main/java/fucoin/configurations/DefaultConfiguration.java b/src/main/java/fucoin/configurations/DefaultConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..f3dd28afde014790af9af61a776592b83ced271e --- /dev/null +++ b/src/main/java/fucoin/configurations/DefaultConfiguration.java @@ -0,0 +1,18 @@ +package fucoin.configurations; + +/** + * + */ +public class DefaultConfiguration extends AbstractConfiguration { + + @Override + public void run() { + initSupervisor(); + spawnWallets(2, true); + } + + @Override + public String getName() { + return "Default Configuration"; + } +} diff --git a/src/main/java/fucoin/configurations/MassWalletConfiguration.java b/src/main/java/fucoin/configurations/MassWalletConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..f4c3587315c45041bf19f6fb3f9bcc4bb6a6dbe7 --- /dev/null +++ b/src/main/java/fucoin/configurations/MassWalletConfiguration.java @@ -0,0 +1,17 @@ +package fucoin.configurations; + +/** + * + */ +public class MassWalletConfiguration extends AbstractConfiguration { + @Override + public void run() { + initSupervisor(); + spawnWallets(200, false); + } + + @Override + public String getName() { + return "Lots of wallets"; + } +}