Merge branch 'jeremi' into dev

# Conflicts:
#	app/src/main/java/lightcontainer/domains/client/StoreProcessor.java
This commit is contained in:
Jérémi N ‘EndMove’ 2022-02-26 15:39:51 +01:00
commit cdb3cee065
Signed by: EndMove
GPG Key ID: 65C4A02E1F5371A4
14 changed files with 278 additions and 77 deletions

View File

@ -3,30 +3,33 @@
*/ */
package lightcontainer; package lightcontainer;
import lightcontainer.domains.StoreMulticastRunnable; import lightcontainer.domains.server.MulticastServerListener;
import lightcontainer.protocol.Protocol; import lightcontainer.domains.server.UnicastServerListener;
import lightcontainer.interfaces.MulticastSPR;
import java.util.HashMap; import lightcontainer.repository.ClientHandlerRepository;
import java.util.Map; import lightcontainer.repository.FileFrontEnd;
import lightcontainer.repository.StoreProcessorRepository;
public class App { 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) { 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; new UnicastServerListener(clientRep, UNICAST_PORT);
String ip = "226.0.0.1"; new MulticastServerListener(storeRep, MULTICAST_IP, MULTICAST_PORT);
StoreMulticastRunnable multicast = new StoreMulticastRunnable(ip, port); FileFrontEnd ffe = new FileFrontEnd(clientRep, storeRep);
(new Thread(multicast)).start();
// Sleep // close repo et client et server.
try { clientRep.close();
Thread.sleep(5000); storeRep.close();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Close
multicast.stop();
} }
} }

View File

@ -1,4 +1,4 @@
package lightcontainer.domains; package lightcontainer.domains.client;
import lightcontainer.interfaces.ClientHandlerFFE; import lightcontainer.interfaces.ClientHandlerFFE;
@ -9,10 +9,11 @@ import java.nio.charset.StandardCharsets;
/** /**
* ClientHandler * ClientHandler
* *
* <!> UNICAST CLIENT <!>
* Class communicating with the client, and * Class communicating with the client, and
* intercepting and sending files to the client. * intercepting and sending files to the client.
* *
* @version 1.0 * @version 1.1
* @since 1.0 * @since 1.0
* *
* @see Runnable * @see Runnable
@ -23,6 +24,7 @@ public class ClientHandler implements Runnable, AutoCloseable {
// Variables // Variables
private ClientHandlerFFE fileFrontEnd; private ClientHandlerFFE fileFrontEnd;
private final Socket client; private final Socket client;
private boolean client_run;
private BufferedReader reader; private BufferedReader reader;
private PrintWriter writer; private PrintWriter writer;
@ -31,6 +33,7 @@ public class ClientHandler implements Runnable, AutoCloseable {
public ClientHandler(Socket client, ClientHandlerFFE ffe) { public ClientHandler(Socket client, ClientHandlerFFE ffe) {
this.fileFrontEnd = ffe; this.fileFrontEnd = ffe;
this.client = client; this.client = client;
this.client_run = false;
initClient(); initClient();
} }
@ -65,14 +68,13 @@ public class ClientHandler implements Runnable, AutoCloseable {
*/ */
@Override @Override
public void run() { public void run() {
while (true) { this.client_run = true;
while (this.client_run) {
try { try {
String command = this.reader.readLine(); String command = this.reader.readLine();
// TODO gestion de la réception de commandes, fichier, ... // TODO gestion de la réception de commandes, fichier, ...
if (command != null) System.out.println("Client: " + command); if (command != null) System.out.println("Client: " + command);
} catch (IOException e) { } catch (IOException ignore) { }
e.printStackTrace();
}
} }
} }
@ -84,6 +86,11 @@ public class ClientHandler implements Runnable, AutoCloseable {
*/ */
@Override @Override
public void close() { public void close() {
if (this.client_run) {
try {
this.client_run = false;
this.client.close();
} catch (IOException ignored) { }
}
} }
} }

View File

@ -1,4 +1,4 @@
package lightcontainer.domains; package lightcontainer.domains.client;
import lightcontainer.interfaces.StoreProcessorFFE; import lightcontainer.interfaces.StoreProcessorFFE;
@ -9,10 +9,11 @@ import java.nio.charset.StandardCharsets;
/** /**
* StoreProcessor * StoreProcessor
* *
* <!> MULTICAST CLIENT <!>
* Class communicating with the storebackend and * Class communicating with the storebackend and
* processing the tasks in the FileFrontEnd * processing the tasks in the FileFrontEnd
* *
* @version 1.0 * @version 1.1
* @since 1.0 * @since 1.0
* *
* @see Runnable * @see Runnable
@ -23,6 +24,7 @@ public class StoreProcessor implements Runnable, AutoCloseable {
// Variables // Variables
private final StoreProcessorFFE fileFrontEnd; private final StoreProcessorFFE fileFrontEnd;
private final Socket store; private final Socket store;
private boolean client_run;
private BufferedReader reader; private BufferedReader reader;
private PrintWriter writer; private PrintWriter writer;
@ -31,16 +33,16 @@ public class StoreProcessor implements Runnable, AutoCloseable {
public StoreProcessor(Socket socket, StoreProcessorFFE ffe) { public StoreProcessor(Socket socket, StoreProcessorFFE ffe) {
this.fileFrontEnd = ffe; this.fileFrontEnd = ffe;
this.store = socket; this.store = socket;
this.client_run = false;
initStore(); initStore();
} }
/** /**
* Initialise the Store's Reader and Writer. * Initialise the Store's Reader and Writer.
* *
* @since 1.0
*
* @see BufferedReader * @see BufferedReader
* @see PrintWriter * @see PrintWriter
* @since 1.0
*/ */
private void initStore() { private void initStore() {
try { try {
@ -65,20 +67,13 @@ public class StoreProcessor implements Runnable, AutoCloseable {
*/ */
@Override @Override
public void run() { public void run() {
while (true) { this.client_run = true;
while (this.client_run) {
try { try {
// Envoie donnée au StoreBackEnd
String command = this.reader.readLine(); String command = this.reader.readLine();
// TODO gestion de la réception de commandes, fichier, ... // TODO gestion de la réception de commandes, fichier, ...
if (command != null) System.out.println("StoreBackEnd: " + command); if (command != null) System.out.println("StoreBackEnd: " + command);
} catch (IOException ignore) { }
// 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);
} }
} }
@ -90,6 +85,11 @@ public class StoreProcessor implements Runnable, AutoCloseable {
*/ */
@Override @Override
public void close() { public void close() {
if (this.client_run) {
try {
this.client_run = false;
this.store.close();
} catch (IOException ignored) { }
}
} }
} }

View File

@ -1,8 +1,10 @@
package lightcontainer.domains; package lightcontainer.domains.server;
import java.net.DatagramPacket; import lightcontainer.domains.client.StoreProcessor;
import java.net.InetAddress; import lightcontainer.interfaces.MulticastSPR;
import java.net.MulticastSocket;
import java.io.IOException;
import java.net.*;
/** /**
* StoreMulticastRunnable * StoreMulticastRunnable
@ -16,18 +18,21 @@ import java.net.MulticastSocket;
* @see Runnable * @see Runnable
* @author Jérémi NIHART <j.nihart@student.helmo.be> * @author Jérémi NIHART <j.nihart@student.helmo.be>
*/ */
public class StoreMulticastRunnable implements Runnable { public class MulticastServerListener implements Runnable {
// Variable // Variable
private final String multicast_address; private final String multicast_address;
private final int multicast_port; private final int multicast_port;
private final MulticastSPR repository;
private final byte[] buffer = new byte[256]; private final byte[] buffer = new byte[256];
private MulticastSocket listener; private MulticastSocket listener;
// Constructor // 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_address = multicast_address;
this.multicast_port = multicast_port; 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 // Create an identifier for the multicast group on the specified ip
InetAddress listener_group = InetAddress.getByName(this.multicast_address); InetAddress listener_group = InetAddress.getByName(this.multicast_address);
// Creation of a packet for the information received // 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 // Add the listener to the multicast group
listener.joinGroup(listener_group); this.listener.joinGroup(listener_group);
while(true) { 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()); String data = new String(packet.getData(), 0, packet.getLength());
// Create a new StoreBacked (try used in the case of an error to maintain the listening loop)
System.out.println(data); // TODO ajouter un controller et lui signaler qu'il y a un nouveau StoreBackEnd 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) { } } catch (Exception ignore) { }
} }
@ -63,7 +76,7 @@ public class StoreMulticastRunnable implements Runnable {
* *
* @since 1.0 * @since 1.0
* *
* @see StoreMulticastRunnable#run() * @see MulticastServerListener#run()
*/ */
public void stop() { public void stop() {
this.listener.close(); this.listener.close();

View File

@ -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.io.IOException;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
public class Server { public class UnicastServerListener {
// Variables // Variables
private ServerSocket server; private ServerSocket server;
private final UnicastCHR repository;
private final int server_port; private final int server_port;
private boolean server_run; private boolean server_run;
// Constructor // Constructor
public Server(int port) { public UnicastServerListener(UnicastCHR repository, int port) {
this.repository = repository;
this.server_port = port; this.server_port = port;
this.server_run = false; this.server_run = false;
repository.setServerListener(this);
} }
/** /**
@ -26,8 +32,10 @@ public class Server {
*/ */
public void start() { public void start() {
try { try {
// Allow looping in the loop and create a socket server
this.server_run = true;
this.server = new ServerSocket(this.server_port); this.server = new ServerSocket(this.server_port);
while (server_run) { while (this.server_run) {
// Accepting connection requests (blocking) // Accepting connection requests (blocking)
Socket client = this.server.accept(); Socket client = this.server.accept();
// Create a new Handler client by passing these dependencies to it // Create a new Handler client by passing these dependencies to it

View File

@ -1,5 +1,10 @@
package lightcontainer.enumerations; package lightcontainer.enumerations;
import lightcontainer.domains.Task;
/**
* Enumeration defining the status of a {@link Task}.
*/
public enum TaskStatus { public enum TaskStatus {
PENDING, PENDING,
PROCESSING, PROCESSING,

View File

@ -1,5 +1,10 @@
package lightcontainer.enumerations; package lightcontainer.enumerations;
import lightcontainer.domains.Task;
/**
* enumeration to define the type of a {@link Task}.
*/
public enum TaskType { public enum TaskType {
SEND, SEND,
RECEIVE, RECEIVE,

View File

@ -1,4 +1,11 @@
package lightcontainer.interfaces; 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 { public interface ClientHandlerFFE {
// functions
} }

View File

@ -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);
}

View File

@ -1,13 +1,15 @@
package lightcontainer.interfaces; package lightcontainer.interfaces;
import lightcontainer.domains.StoreProcessor; import lightcontainer.domains.client.StoreProcessor;
import lightcontainer.repository.FileFrontEnd;
public interface StoreProcessorFFE {
/** /**
* Permet à un {@link StoreProcessor} d'avertir le FFE qu'il est disponible * A communication interface between a {@link StoreProcessor} and the {@link FileFrontEnd}.
* @param store */
public interface StoreProcessorFFE {
/**
* 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); void onStoreAvailable(StoreProcessor store);
} }

View File

@ -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);
}

View File

@ -1,20 +1,68 @@
package lightcontainer.repository; 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.ArrayList;
import java.util.List; import java.util.List;
// TODO : C'est genre un ClientHandlerManager quoi hein, normal qu'il fasse blinder de chose ;)
public class ClientHandlerRepository { /**
* ClientHandlerRepository
*
* Repository storing ClientHandler class.
* Contains some utility functions.
*
* @version 1.0
* @since 1.0
*
* @see ClientHandler
* @see AutoCloseable
* @author Jérémi NIHART <j.nihart@student.helmo.be>
*/
public class ClientHandlerRepository implements AutoCloseable, UnicastCHR {
// Variable // Variable
private final List<ClientHandler> handlers = new ArrayList<>(); private final List<ClientHandler> handlers;
private UnicastServerListener server;
// Constructor // Constructor
public ClientHandlerRepository() { 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) { public void addClient(ClientHandler client) {
this.handlers.add(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);
}
} }

View File

@ -1,14 +1,11 @@
package lightcontainer.repository; package lightcontainer.repository;
import lightcontainer.domains.ClientHandler; import lightcontainer.domains.client.StoreProcessor;
import lightcontainer.domains.StoreProcessor;
import lightcontainer.domains.Task; import lightcontainer.domains.Task;
import lightcontainer.interfaces.ClientHandlerFFE; import lightcontainer.interfaces.ClientHandlerFFE;
import lightcontainer.interfaces.StoreProcessorFFE; import lightcontainer.interfaces.StoreProcessorFFE;
import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.LinkedList;
import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedDeque;
public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE { public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE {
@ -28,7 +25,6 @@ public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE {
*/ */
public void alertStoreProcessors(Task task) { public void alertStoreProcessors(Task task) {
// On avertit les stor processors d'une nouvelle tâche // On avertit les stor processors d'une nouvelle tâche
} }
/** /**

View File

@ -1,5 +1,67 @@
package lightcontainer.repository; 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 <j.nihart@student.helmo.be>
*/
public class StoreProcessorRepository implements AutoCloseable, MulticastSPR {
// Variables
private final List<StoreProcessor> 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);
}
} }