diff --git a/.idea/.gitignore b/.idea/.gitignore index 13566b8..73f69e0 100644 --- a/.idea/.gitignore +++ b/.idea/.gitignore @@ -1,8 +1,8 @@ # Default ignored files /shelf/ /workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ # Datasource local storage ignored files /dataSources/ /dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..d8e9561 --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..601f39c --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/libraries-with-intellij-classes.xml b/.idea/libraries-with-intellij-classes.xml new file mode 100644 index 0000000..9fa3156 --- /dev/null +++ b/.idea/libraries-with-intellij-classes.xml @@ -0,0 +1,65 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 5d98256..3e79c5f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,7 +4,5 @@ - - - + \ No newline at end of file diff --git a/app/src/main/java/lightcontainer/App.java b/app/src/main/java/lightcontainer/App.java index aa63180..e590d9d 100644 --- a/app/src/main/java/lightcontainer/App.java +++ b/app/src/main/java/lightcontainer/App.java @@ -3,12 +3,30 @@ */ package lightcontainer; -public class App { - public String getGreeting() { - return "Hello World!"; - } +import lightcontainer.domains.StoreMulticastRunnable; +import lightcontainer.protocol.Protocol; +import java.util.HashMap; +import java.util.Map; + +public class App { public static void main(String[] args) { - System.out.println(new App().getGreeting()); + System.out.println("Hello World !"); + + int port = 42500; + String ip = "226.0.0.1"; + + StoreMulticastRunnable multicast = new StoreMulticastRunnable(ip, port); + (new Thread(multicast)).start(); + + // Sleep + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + // Close + multicast.stop(); } } diff --git a/app/src/main/java/lightcontainer/domains/FileFrontEnd.java b/app/src/main/java/lightcontainer/domains/FileFrontEnd.java new file mode 100644 index 0000000..6916615 --- /dev/null +++ b/app/src/main/java/lightcontainer/domains/FileFrontEnd.java @@ -0,0 +1,5 @@ +package lightcontainer.domains; + +public class FileFrontEnd { + +} diff --git a/app/src/main/java/lightcontainer/domains/StoreMulticastRunnable.java b/app/src/main/java/lightcontainer/domains/StoreMulticastRunnable.java new file mode 100644 index 0000000..f6aede3 --- /dev/null +++ b/app/src/main/java/lightcontainer/domains/StoreMulticastRunnable.java @@ -0,0 +1,70 @@ +package lightcontainer.domains; + +import java.net.DatagramPacket; +import java.net.InetAddress; +import java.net.MulticastSocket; + +/** + * StoreMulticastRunnable + * + * Class listening to the announcement of new StoreBackEnd. + * Allowing it to be used as a storage unit. + * + * @version 1.0 + * @since 1.0 + * + * @see Runnable + * @author Jérémi NIHART + */ +public class StoreMulticastRunnable implements Runnable { + // Variable + private final String multicast_address; + private final int multicast_port; + + private final byte[] buffer = new byte[256]; + private MulticastSocket listener; + + // Constructor + public StoreMulticastRunnable(String multicast_address, int multicast_port) { + this.multicast_address = multicast_address; + this.multicast_port = multicast_port; + } + + /** + * Start Multicast listening on indicated port and IP group. + * + * @since 1.0 + * + * @see MulticastSocket#receive(DatagramPacket) + * @see DatagramPacket + */ + @Override + public void run() { + try { + // Create a new listening socket + this.listener = new MulticastSocket(this.multicast_port); + // Create an identifier for the multicast group on the specified ip + InetAddress listener_group = InetAddress.getByName(this.multicast_address); + // Creation of a packet for the information received + DatagramPacket packet = new DatagramPacket(buffer, buffer.length); + // Add the listener to the multicast group + listener.joinGroup(listener_group); + while(true) { + listener.receive(packet); + String data = new String(packet.getData(), 0, packet.getLength()); + System.out.println(data); // TODO ajouter un controller et lui signaler qu'il y a un nouveau StoreBackEnd + } + } catch (Exception ignore) { } + } + + /** + * Closes the MulticastSocket connection and aborts the listening and infinite listening loop. + * + * @since 1.0 + * + * @see StoreMulticastRunnable#run() + */ + public void stop() { + this.listener.close(); + } +} diff --git a/app/src/main/java/lightcontainer/protocol/HelloRule.java b/app/src/main/java/lightcontainer/protocol/HelloRule.java new file mode 100644 index 0000000..c9c2b94 --- /dev/null +++ b/app/src/main/java/lightcontainer/protocol/HelloRule.java @@ -0,0 +1,31 @@ +package lightcontainer.protocol; + +public class HelloRule extends Protocol { + // Variables + + // Constructor + protected HelloRule() { + super("HELLO", "HELLO "); // TODO : add the regex here (sbe_hello = "HELLO bl domain bl port line") + } + + /** + * Execute the rule on a command. + * + * This function allows you to check a command and process those groups (parameters) + * use the utility functions of {@link Protocol} to facilitate processing, see @see. + * + * @param cmd Command on which to execute the rule. + * @see Protocol#execute(String) + * @see #matcherCheck(String) + * @see #matcherGetGroups() + * @since 1.0 + */ + @Override + public void execute(String cmd) { + if (matcherCheck(cmd)) { + System.out.println("Good rule ;-) !"); + } else { + System.out.println("OUPPS unknown rule !"); + } + } +} diff --git a/app/src/main/java/lightcontainer/protocol/Protocol.java b/app/src/main/java/lightcontainer/protocol/Protocol.java new file mode 100644 index 0000000..e7449f3 --- /dev/null +++ b/app/src/main/java/lightcontainer/protocol/Protocol.java @@ -0,0 +1,125 @@ +package lightcontainer.protocol; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Protocol + * + * Class allowing to define new rules for the LightContainer protocol, + * also provides utility functions to work with regexes and the command to compare. + * + * @version 1.0 + * @since 1.0 + * + * @see Pattern + * @author Jérémi NIHART + */ +public abstract class Protocol { + // Variables + private final String rule; + private final Pattern rulePattern; + private List groups; + + /** + * Protocol constructor + * @param rule Command (e.g: LOGIN). + * @param regex Regex to compile and use for this command (e.g: LOGIN ([A-Z0-9a-z]{1,20})). + * Do not forget to define the groups in the regex. + */ + protected Protocol(String rule, String regex) { + this.rule = rule; + this.rulePattern = Pattern.compile(regex); + } + + /** + * Retrieve, the name of the Rule. + * + * @return Name of this rule. + * + * @since 1.0 + */ + public String getRule() { + return this.rule; + } + + /** + * Check if a command matches the rule with the rule matcher. + * + * @return True : if the command match with the rule. + * False though. + * @param cmd Command to verify with the rule matcher. + * + * @since 1.0 + */ + protected boolean matcherCheck(String cmd) { + Matcher ruleMatcher = this.rulePattern.matcher(cmd); + if (ruleMatcher.matches()) { + this.groups = new ArrayList<>(); + for (int i=1; i <= ruleMatcher.groupCount(); i++) this.groups.add(ruleMatcher.group(i)); + return true; + } + return false; + } + + /** + * Get a list of all the groups extracted from the previously matched command with {@link #matcherCheck(String)}. + * + * Requires to have run {@link #matcherCheck(String)} + * + * @return String list containing all the groups extrapolated from the command. + * + * @since 1.0 + * + * @see Protocol#matcherCheck(String) + */ + protected List matcherGetGroups() { + return this.groups; + } + + /** + * Execute the rule on a command. + * + * This function allows you to check a command and process those groups (parameters) + * use the utility functions of {@link Protocol} to facilitate processing, see @see. + * + * @param cmd Command on which to execute the rule. + * + * @since 1.0 + * + * @see Protocol#execute(String) + * @see #matcherCheck(String) + * @see #matcherGetGroups() + */ + public abstract void execute(String cmd); + + /** + * Retrieve, the hashcode of the rule. + * + * @return Rule hashcode. + * + * @since 1.0 + */ + @Override + public int hashCode() { + return rule.hashCode() % 8; + } + + /** + * Compare the equality of two rules. + * + * @return True : if the rules are equals + * False if not. + * + * @since 1.0 + */ + @Override + public boolean equals(final Object obj) { + if (this == obj) return true; + if (!(obj instanceof Protocol)) return false; + final Protocol other = (Protocol) obj; + return hashCode() == other.hashCode(); + } +} diff --git a/app/src/test/java/lightcontainer/AppTest.java b/app/src/test/java/lightcontainer/AppTest.java index f435009..9d64c1d 100644 --- a/app/src/test/java/lightcontainer/AppTest.java +++ b/app/src/test/java/lightcontainer/AppTest.java @@ -7,8 +7,8 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; class AppTest { - @Test void appHasAGreeting() { - App classUnderTest = new App(); - assertNotNull(classUnderTest.getGreeting(), "app should have a greeting"); - } +// @Test void appHasAGreeting() { +// App classUnderTest = new App(); +// assertNotNull(classUnderTest.getGreeting(), "app should have a greeting"); +// } }