diff --git a/app/src/main/java/lightcontainer/App.java b/app/src/main/java/lightcontainer/App.java index e590d9d..47a4788 100644 --- a/app/src/main/java/lightcontainer/App.java +++ b/app/src/main/java/lightcontainer/App.java @@ -3,30 +3,33 @@ */ package lightcontainer; -import lightcontainer.domains.StoreMulticastRunnable; -import lightcontainer.protocol.Protocol; - -import java.util.HashMap; -import java.util.Map; +import lightcontainer.domains.server.MulticastServerListener; +import lightcontainer.domains.server.UnicastServerListener; +import lightcontainer.interfaces.MulticastSPR; +import lightcontainer.repository.ClientHandlerRepository; +import lightcontainer.repository.FileFrontEnd; +import lightcontainer.repository.StoreProcessorRepository; public class App { + // Constant config server + // -- Unicast client port + private static final int UNICAST_PORT = 8500; + // -- Multicast listener ip, port + private static final String MULTICAST_IP = "226.0.0.1"; + private static final int MULTICAST_PORT = 42500; + public static void main(String[] args) { - System.out.println("Hello World !"); + // Create all repository + ClientHandlerRepository clientRep = new ClientHandlerRepository(); + StoreProcessorRepository storeRep = new StoreProcessorRepository(); - int port = 42500; - String ip = "226.0.0.1"; + new UnicastServerListener(clientRep, UNICAST_PORT); + new MulticastServerListener(storeRep, MULTICAST_IP, MULTICAST_PORT); - StoreMulticastRunnable multicast = new StoreMulticastRunnable(ip, port); - (new Thread(multicast)).start(); + FileFrontEnd ffe = new FileFrontEnd(clientRep, storeRep); - // Sleep - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - // Close - multicast.stop(); + // close repo et client et server. + clientRep.close(); + storeRep.close(); } } diff --git a/app/src/main/java/lightcontainer/domains/ClientHandler.java b/app/src/main/java/lightcontainer/domains/client/ClientHandler.java similarity index 82% rename from app/src/main/java/lightcontainer/domains/ClientHandler.java rename to app/src/main/java/lightcontainer/domains/client/ClientHandler.java index 8c1fb15..9dc6100 100644 --- a/app/src/main/java/lightcontainer/domains/ClientHandler.java +++ b/app/src/main/java/lightcontainer/domains/client/ClientHandler.java @@ -1,4 +1,4 @@ -package lightcontainer.domains; +package lightcontainer.domains.client; import lightcontainer.interfaces.ClientHandlerFFE; @@ -9,10 +9,11 @@ import java.nio.charset.StandardCharsets; /** * ClientHandler * + * UNICAST CLIENT * Class communicating with the client, and * intercepting and sending files to the client. * - * @version 1.0 + * @version 1.1 * @since 1.0 * * @see Runnable @@ -23,6 +24,7 @@ public class ClientHandler implements Runnable, AutoCloseable { // Variables private ClientHandlerFFE fileFrontEnd; private final Socket client; + private boolean client_run; private BufferedReader reader; private PrintWriter writer; @@ -31,6 +33,7 @@ public class ClientHandler implements Runnable, AutoCloseable { public ClientHandler(Socket client, ClientHandlerFFE ffe) { this.fileFrontEnd = ffe; this.client = client; + this.client_run = false; initClient(); } @@ -65,14 +68,13 @@ public class ClientHandler implements Runnable, AutoCloseable { */ @Override public void run() { - while (true) { + this.client_run = true; + while (this.client_run) { try { String command = this.reader.readLine(); // TODO gestion de la réception de commandes, fichier, ... if (command != null) System.out.println("Client: " + command); - } catch (IOException e) { - e.printStackTrace(); - } + } catch (IOException ignore) { } } } @@ -84,6 +86,11 @@ public class ClientHandler implements Runnable, AutoCloseable { */ @Override public void close() { - + if (this.client_run) { + try { + this.client_run = false; + this.client.close(); + } catch (IOException ignored) { } + } } } diff --git a/app/src/main/java/lightcontainer/domains/StoreProcessor.java b/app/src/main/java/lightcontainer/domains/client/StoreProcessor.java similarity index 76% rename from app/src/main/java/lightcontainer/domains/StoreProcessor.java rename to app/src/main/java/lightcontainer/domains/client/StoreProcessor.java index fc4f721..f9b56a0 100644 --- a/app/src/main/java/lightcontainer/domains/StoreProcessor.java +++ b/app/src/main/java/lightcontainer/domains/client/StoreProcessor.java @@ -1,4 +1,4 @@ -package lightcontainer.domains; +package lightcontainer.domains.client; import lightcontainer.interfaces.StoreProcessorFFE; @@ -9,10 +9,11 @@ import java.nio.charset.StandardCharsets; /** * StoreProcessor * + * MULTICAST CLIENT * Class communicating with the storebackend and * processing the tasks in the FileFrontEnd * - * @version 1.0 + * @version 1.1 * @since 1.0 * * @see Runnable @@ -23,6 +24,7 @@ public class StoreProcessor implements Runnable, AutoCloseable { // Variables private final StoreProcessorFFE fileFrontEnd; private final Socket store; + private boolean client_run; private BufferedReader reader; private PrintWriter writer; @@ -31,16 +33,16 @@ public class StoreProcessor implements Runnable, AutoCloseable { public StoreProcessor(Socket socket, StoreProcessorFFE ffe) { this.fileFrontEnd = ffe; this.store = socket; + this.client_run = false; initStore(); } /** * Initialise the Store's Reader and Writer. * - * @since 1.0 - * - * @see BufferedReader - * @see PrintWriter + * @see BufferedReader + * @see PrintWriter + * @since 1.0 */ private void initStore() { try { @@ -61,24 +63,17 @@ public class StoreProcessor implements Runnable, AutoCloseable { * Thread Function * Start the dialogue with the storebackend. * - * @since 1.0 + * @since 1.0 */ @Override public void run() { - while (true) { + this.client_run = true; + while (this.client_run) { try { - // Envoie donnée au StoreBackEnd String command = this.reader.readLine(); // TODO gestion de la réception de commandes, fichier, ... if (command != null) System.out.println("StoreBackEnd: " + command); - - // Réception donnée du StoreBackEnd - } catch (IOException e) { - e.printStackTrace(); - } - - // Alerter le FileFrontEnd que ce store processor est disponible pour gérer de nouvelle demande - fileFrontEnd.onStoreAvailable(this); + } catch (IOException ignore) { } } } @@ -86,10 +81,15 @@ public class StoreProcessor implements Runnable, AutoCloseable { * AutoClosable Function * Close the Storage thread and resources. * - * @since 1.0 + * @since 1.0 */ @Override public void close() { - + if (this.client_run) { + try { + this.client_run = false; + this.store.close(); + } catch (IOException ignored) { } + } } } diff --git a/app/src/main/java/lightcontainer/domains/StoreMulticastRunnable.java b/app/src/main/java/lightcontainer/domains/server/MulticastServerListener.java similarity index 52% rename from app/src/main/java/lightcontainer/domains/StoreMulticastRunnable.java rename to app/src/main/java/lightcontainer/domains/server/MulticastServerListener.java index 835b0dd..e54371b 100644 --- a/app/src/main/java/lightcontainer/domains/StoreMulticastRunnable.java +++ b/app/src/main/java/lightcontainer/domains/server/MulticastServerListener.java @@ -1,8 +1,10 @@ -package lightcontainer.domains; +package lightcontainer.domains.server; -import java.net.DatagramPacket; -import java.net.InetAddress; -import java.net.MulticastSocket; +import lightcontainer.domains.client.StoreProcessor; +import lightcontainer.interfaces.MulticastSPR; + +import java.io.IOException; +import java.net.*; /** * StoreMulticastRunnable @@ -16,18 +18,21 @@ import java.net.MulticastSocket; * @see Runnable * @author Jérémi NIHART */ -public class StoreMulticastRunnable implements Runnable { +public class MulticastServerListener implements Runnable { // Variable private final String multicast_address; private final int multicast_port; + private final MulticastSPR repository; private final byte[] buffer = new byte[256]; private MulticastSocket listener; // Constructor - public StoreMulticastRunnable(String multicast_address, int multicast_port) { + public MulticastServerListener(MulticastSPR repository, String multicast_address, int multicast_port) { + this.repository = repository; this.multicast_address = multicast_address; this.multicast_port = multicast_port; + repository.setServerListener(this); } /** @@ -46,14 +51,22 @@ public class StoreMulticastRunnable implements Runnable { // 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); + DatagramPacket packet = new DatagramPacket(this.buffer, this.buffer.length); // Add the listener to the multicast group - listener.joinGroup(listener_group); + this.listener.joinGroup(listener_group); while(true) { - listener.receive(packet); + // Read the packet received and build a string of characters + this.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 + // Create a new StoreBacked (try used in the case of an error to maintain the listening loop) + try { + // TODO Récupérer le port du message du packet et le setup (add description of the line). + Socket socket = new Socket(packet.getAddress(), 2500); + // Create the store processor + StoreProcessor storeProcessor = new StoreProcessor(socket, null); // TODO : Voir comment on procède get via repo ou ici ?! + // Add the store processor to its repository + this.repository.addStore(storeProcessor); + } catch (IOException ignore) { } } } catch (Exception ignore) { } } @@ -63,7 +76,7 @@ public class StoreMulticastRunnable implements Runnable { * * @since 1.0 * - * @see StoreMulticastRunnable#run() + * @see MulticastServerListener#run() */ public void stop() { this.listener.close(); diff --git a/app/src/main/java/lightcontainer/domains/Server.java b/app/src/main/java/lightcontainer/domains/server/UnicastServerListener.java similarity index 75% rename from app/src/main/java/lightcontainer/domains/Server.java rename to app/src/main/java/lightcontainer/domains/server/UnicastServerListener.java index 5c32cd1..c5ca8cd 100644 --- a/app/src/main/java/lightcontainer/domains/Server.java +++ b/app/src/main/java/lightcontainer/domains/server/UnicastServerListener.java @@ -1,19 +1,25 @@ -package lightcontainer.domains; +package lightcontainer.domains.server; + +import lightcontainer.domains.client.ClientHandler; +import lightcontainer.interfaces.UnicastCHR; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; -public class Server { +public class UnicastServerListener { // Variables private ServerSocket server; + private final UnicastCHR repository; private final int server_port; private boolean server_run; // Constructor - public Server(int port) { + public UnicastServerListener(UnicastCHR repository, int port) { + this.repository = repository; this.server_port = port; this.server_run = false; + repository.setServerListener(this); } /** @@ -26,8 +32,10 @@ public class Server { */ public void start() { try { + // Allow looping in the loop and create a socket server + this.server_run = true; this.server = new ServerSocket(this.server_port); - while (server_run) { + while (this.server_run) { // Accepting connection requests (blocking) Socket client = this.server.accept(); // Create a new Handler client by passing these dependencies to it diff --git a/app/src/main/java/lightcontainer/enumerations/TaskStatus.java b/app/src/main/java/lightcontainer/enumerations/TaskStatus.java index 64261f9..4113565 100644 --- a/app/src/main/java/lightcontainer/enumerations/TaskStatus.java +++ b/app/src/main/java/lightcontainer/enumerations/TaskStatus.java @@ -1,5 +1,10 @@ package lightcontainer.enumerations; +import lightcontainer.domains.Task; + +/** + * Enumeration defining the status of a {@link Task}. + */ public enum TaskStatus { PENDING, PROCESSING, diff --git a/app/src/main/java/lightcontainer/enumerations/TaskType.java b/app/src/main/java/lightcontainer/enumerations/TaskType.java index 3d4054c..347e6ce 100644 --- a/app/src/main/java/lightcontainer/enumerations/TaskType.java +++ b/app/src/main/java/lightcontainer/enumerations/TaskType.java @@ -1,5 +1,10 @@ package lightcontainer.enumerations; +import lightcontainer.domains.Task; + +/** + * enumeration to define the type of a {@link Task}. + */ public enum TaskType { SEND, RECEIVE, diff --git a/app/src/main/java/lightcontainer/interfaces/ClientHandlerFFE.java b/app/src/main/java/lightcontainer/interfaces/ClientHandlerFFE.java index a1783f7..a3a303f 100644 --- a/app/src/main/java/lightcontainer/interfaces/ClientHandlerFFE.java +++ b/app/src/main/java/lightcontainer/interfaces/ClientHandlerFFE.java @@ -1,4 +1,11 @@ package lightcontainer.interfaces; +import lightcontainer.domains.client.ClientHandler; +import lightcontainer.repository.FileFrontEnd; + +/** + * A communication interface between a {@link ClientHandler} and the {@link FileFrontEnd}. + */ public interface ClientHandlerFFE { + // functions } diff --git a/app/src/main/java/lightcontainer/interfaces/MulticastSPR.java b/app/src/main/java/lightcontainer/interfaces/MulticastSPR.java new file mode 100644 index 0000000..b2108ec --- /dev/null +++ b/app/src/main/java/lightcontainer/interfaces/MulticastSPR.java @@ -0,0 +1,22 @@ +package lightcontainer.interfaces; + +import lightcontainer.domains.client.StoreProcessor; +import lightcontainer.domains.server.MulticastServerListener; +import lightcontainer.repository.StoreProcessorRepository; + +/** + * A communication interface between a {@link StoreProcessor} and the {@link StoreProcessorRepository}. + */ +public interface MulticastSPR { + /** + * Setter, allow to define the ServerListener of a repository. + * @param server ServerListener to set as default. + */ + void setServerListener(MulticastServerListener server); + + /** + * Add a StorePorcessor. + * @param store Store processor to add. + */ + void addStore(StoreProcessor store); +} diff --git a/app/src/main/java/lightcontainer/interfaces/StoreProcessorFFE.java b/app/src/main/java/lightcontainer/interfaces/StoreProcessorFFE.java index 7a5ffb6..5e95d5f 100644 --- a/app/src/main/java/lightcontainer/interfaces/StoreProcessorFFE.java +++ b/app/src/main/java/lightcontainer/interfaces/StoreProcessorFFE.java @@ -1,13 +1,15 @@ package lightcontainer.interfaces; -import lightcontainer.domains.StoreProcessor; +import lightcontainer.domains.client.StoreProcessor; +import lightcontainer.repository.FileFrontEnd; +/** + * A communication interface between a {@link StoreProcessor} and the {@link FileFrontEnd}. + */ public interface StoreProcessorFFE { - /** - * Permet à un {@link StoreProcessor} d'avertir le FFE qu'il est disponible - * @param store + * Allows a {@link StoreProcessor} to notify the FFE that it's available. + * @param store The store processor that is now available. */ void onStoreAvailable(StoreProcessor store); - } diff --git a/app/src/main/java/lightcontainer/interfaces/UnicastCHR.java b/app/src/main/java/lightcontainer/interfaces/UnicastCHR.java new file mode 100644 index 0000000..599093c --- /dev/null +++ b/app/src/main/java/lightcontainer/interfaces/UnicastCHR.java @@ -0,0 +1,23 @@ +package lightcontainer.interfaces; + +import lightcontainer.domains.client.ClientHandler; +import lightcontainer.domains.server.MulticastServerListener; +import lightcontainer.domains.server.UnicastServerListener; +import lightcontainer.repository.ClientHandlerRepository; + +/** + * A communication interface between a {@link ClientHandler} and the {@link ClientHandlerRepository}. + */ +public interface UnicastCHR { + /** + * Setter, allow to define the ServerListener of a repository. + * @param server ServerListener to set as default. + */ + void setServerListener(UnicastServerListener server); + + /** + * Add a ClientHandler. + * @param client Client Handler to add. + */ + void addClient(ClientHandler client); +} diff --git a/app/src/main/java/lightcontainer/repository/ClientHandlerRepository.java b/app/src/main/java/lightcontainer/repository/ClientHandlerRepository.java index 66f183b..8cc9383 100644 --- a/app/src/main/java/lightcontainer/repository/ClientHandlerRepository.java +++ b/app/src/main/java/lightcontainer/repository/ClientHandlerRepository.java @@ -1,20 +1,68 @@ package lightcontainer.repository; -import lightcontainer.domains.ClientHandler; +import lightcontainer.domains.client.ClientHandler; +import lightcontainer.domains.server.UnicastServerListener; +import lightcontainer.interfaces.UnicastCHR; import java.util.ArrayList; import java.util.List; - -public class ClientHandlerRepository { +// TODO : C'est genre un ClientHandlerManager quoi hein, normal qu'il fasse blinder de chose ;) +/** + * ClientHandlerRepository + * + * Repository storing ClientHandler class. + * Contains some utility functions. + * + * @version 1.0 + * @since 1.0 + * + * @see ClientHandler + * @see AutoCloseable + * @author Jérémi NIHART + */ +public class ClientHandlerRepository implements AutoCloseable, UnicastCHR { // Variable - private final List handlers = new ArrayList<>(); + private final List handlers; + private UnicastServerListener server; // Constructor public ClientHandlerRepository() { - + this.handlers = new ArrayList<>(); } + /** + * Setter, allow to define the ServerListener of a repository. + * @param server ServerListener to set as default. + * + * @since 1.0 + */ + @Override + public void setServerListener(UnicastServerListener server) { + this.server = server; + } + + /** + * Add a ClientHandler. + * @param client Client Handler to add. + * + * @since 1.0 + */ + @Override public void addClient(ClientHandler client) { this.handlers.add(client); } + + /** + * AutoClosable Function + * Closes all ClientHandlers stored in this repository and deallocates all resources. + * + * @since 1.0 + */ + @Override + public void close() { + // Stop the server. + this.server.stop(); + // Stop each clients. + this.handlers.forEach(ClientHandler::close); + } } diff --git a/app/src/main/java/lightcontainer/repository/FileFrontEnd.java b/app/src/main/java/lightcontainer/repository/FileFrontEnd.java index d7dfde2..b7028c5 100644 --- a/app/src/main/java/lightcontainer/repository/FileFrontEnd.java +++ b/app/src/main/java/lightcontainer/repository/FileFrontEnd.java @@ -1,14 +1,11 @@ package lightcontainer.repository; -import lightcontainer.domains.ClientHandler; -import lightcontainer.domains.StoreProcessor; +import lightcontainer.domains.client.StoreProcessor; import lightcontainer.domains.Task; import lightcontainer.interfaces.ClientHandlerFFE; import lightcontainer.interfaces.StoreProcessorFFE; -import java.util.Collections; import java.util.Deque; -import java.util.LinkedList; import java.util.concurrent.ConcurrentLinkedDeque; public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE { @@ -28,7 +25,6 @@ public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE { */ public void alertStoreProcessors(Task task) { // On avertit les stor processors d'une nouvelle tâche - } /** diff --git a/app/src/main/java/lightcontainer/repository/StoreProcessorRepository.java b/app/src/main/java/lightcontainer/repository/StoreProcessorRepository.java index a330360..7ed9a74 100644 --- a/app/src/main/java/lightcontainer/repository/StoreProcessorRepository.java +++ b/app/src/main/java/lightcontainer/repository/StoreProcessorRepository.java @@ -1,5 +1,67 @@ package lightcontainer.repository; -public class StoreProcessorRepository { +import lightcontainer.domains.client.StoreProcessor; +import lightcontainer.domains.server.MulticastServerListener; +import lightcontainer.interfaces.MulticastSPR; +import java.util.ArrayList; +import java.util.List; +// TODO : C'est genre un ClientHandlerManager quoi hein, normal qu'il fasse blinder de chose ;) +/** + * StoreProcessorRepository + * + * Repository storing StorePorcessor class. + * Contains some utility functions. + * + * @version 1.0 + * @since 1.0 + * + * @see StoreProcessor + * @author Jérémi NIHART + */ +public class StoreProcessorRepository implements AutoCloseable, MulticastSPR { + // Variables + private final List handlers; + private MulticastServerListener server; + + // Constructor + public StoreProcessorRepository() { + this.handlers = new ArrayList<>(); + } + + /** + * Setter, allow to define the ServerListener of a repository. + * @param server ServerListener to set as default. + * + * @since 1.0 + */ + @Override + public void setServerListener(MulticastServerListener server) { + this.server = server; + } + + /** + * Add a StorePorcessor. + * @param store Store processor to add. + * + * @since 1.0 + */ + @Override + public void addStore(StoreProcessor store) { + this.handlers.add(store); + } + + /** + * AutoClosable Function + * Closes all StoreProcessor stored in this repository and deallocates all resources. + * + * @since 1.0 + */ + @Override + public void close() { + // Stop the server. + this.server.stop(); + // Close each client. + this.handlers.forEach(StoreProcessor::close); + } }